Reputation: 9935
How can I do the asynchronous process in java?
In my program, there are two process.
I would like to do parallel process for sendMessage()
and addNewOrder()
.
Actually, I have no experience in Multi-Threading
.
OrderService.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
}
I want, insert()
method need to run even sendMessage()
process is failed.
BTW, Should I use JMS because my development environment is
Upvotes: 1
Views: 194
Reputation: 29856
This is a bad idea. In fact, the current order of operations needs to be changed. You need to save to the DB first, then notify the customer:
public void addNewOrder(Order order) {
orderDAO.insert(order);
mailer.sendMessage(order.getCustomer());
}
If saving the order fails, you do not want to send the customer a confirmation notice! This would be misleading the customer. They would think their order has been placed when in fact the order was completely lost.
In fact, you need some error handling in the event the order fails to save. Upon error, the customer should be given some kind of error notification in the response page. The error handling probably shouldn't be in this method, but put it somewhere.
You could have the e-mail be sent by another thread if you're concerned about the request blocking too long while the e-mail is being sent. This does introduce some risk that the notification e-mail may be lost if it fails to send. If you're willing to take that risk, you should only even try to send the e-mail if saving the order succeeds. If you do that, then this might be a highly simplified version of the code you could use for that:
public void addNewOrder(Order order) {
orderDAO.insert(order);
Runnable mailRunnable = new Runnable() {
public void run() {
mailer.sendMessage(order.getCustomer())
}
}
new Thread(mailRunnable).start();
}
Thread
class documentation is here, and Runnable
is here.
I'm not sure the closure aspect (capturing mailer
and order
) works here. If not, implement Runnable
separately and make them arguments to the constructor. The Runnable
needs error handling, too. (It should probably just log any errors somewhere.)
Upvotes: 2
Reputation: 700
you can use the ExecutorService for more elegant solution :
// 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();
}
Upvotes: 0
Reputation: 17422
An idea of how to do it:
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();
}
Upvotes: 0