1

如何在java中执行异步过程?

在我的程序中,有两个过程。

  1. 通过邮件将通知消息发送给客户。
  2. 将订单信息添加到数据库。

我想为sendMessage()和做并行处理addNewOrder()。其实,我没有经验Multi-Threading

订单服务.java

public void addNewOrder(Order order) {
    mailer.sendMessage(order.getCustomer());
    orderDAO.insert(order);
}

SMTPMailer.java

public void sendMessage(Customer customer) {
    // send notification message
}

OrderDAO.java

public void insert(Order order) {
    // insert order to database
}

我想要,即使进程失败,insert()方法也需要运行。sendMessage()

顺便说一句,我应该使用 JMS,因为我的开发环境是

  1. JBoss 7.1
  2. 春天 3.0。
  3. JSF 2.0 和 Primefaces 3.5
  4. JPA 2.0
  5. JBoss 缝 2.3
4

3 回答 3

2

这是一个坏主意。事实上,当前的操作顺序需要改变。您需要先保存到数据库,然后通知客户:

public void addNewOrder(Order order) {
    orderDAO.insert(order);
    mailer.sendMessage(order.getCustomer());
}

为什么?

如果保存订单失败,您不想给客户发送确认通知!这会误导客户。他们会认为他们的订单已经下达,而实际上订单已经完全丢失

事实上,如果订单保存失败,您需要一些错误处理。发生错误时,应在响应页面中向客户提供某种错误通知。错误处理可能不应该在这个方法中,而是放在某个地方。

那就是说...

如果您担心在发送电子邮件时请求阻塞太久,您可以让另一个线程发送电子邮件。这确实会带来一些风险,即如果发送失败,通知电子邮件可能会丢失。如果您愿意承担这个风险,您甚至应该只在保存订单成功的情况下尝试发送电子邮件。如果您这样做,那么这可能是您可以使用的代码的高度简化版本:

public void addNewOrder(Order order) {
    orderDAO.insert(order);
    Runnable mailRunnable = new Runnable() {
        public void run() {
            mailer.sendMessage(order.getCustomer())
        }
    }
    new Thread(mailRunnable).start();
}

Thread类文档在这里也在Runnable这里。

我不确定闭包方面(捕获mailerorder)在这里是否有效。如果不是,Runnable请单独实现并将它们作为构造函数的参数。Runnable也需要错误处理。(它可能应该只是在某处记录任何错误。)

于 2013-07-29T07:25:21.690 回答
0

如何做到这一点的想法:

public void addNewOrder(Order order) {

    Thread sendMessageThread = new Thread(new Runnable() {

        public void run() {
            mailer.sendMessage(order.getCustomer());
        }

    });

    Thread insertOrderThread = new Thread(new Runnable() {

        public void run() {
            orderDAO.insert(order);
        }

    });

    // Start both threads;
    sendMessageThread.start();
    insertOrderThread.start();

    // wait for them to finish
    sendMessageThread.join();
    insertOrderThread.join();
}
于 2013-07-29T06:25:56.500 回答
0

您可以使用 ExecutorService 获得更优雅的解决方案:

// prepare the callables 
    class MailerCallable implements Callable<Void>{

        Customer customer;
        public MailerCallable(Customer customer){
            this.customer = customer;
        }
        @Override
        public Void call() throws Exception {
            mailer.sendMessage(customer);
            return null;
        }
    }

    class OrderCallable implements Callable<Void>{

        Order order;

        public OrderCallable(Order order){
            this.order = order;
        }
        @Override
        public Void call() throws Exception {
            orderDAO.insert(order);
            return null;
        }
    }

    // prepare the executor service
    ExecutorService service = Executors.newFixedThreadPool(2);
    List<Callable<Void>> callables = new ArrayList<Callable<Void>>();
    callables.add(new MailerCallable(order.getCustomer()));
    callables.add(new OrderCallable(order));

    // execute all and wait for the results
    try{
        service.invokeAll(callables);
    }
    catch (InterruptedException e){
        e.printStackTrace();
    }
于 2013-07-29T08:40:49.307 回答