spring3.x
之后,已经内置了@Async来完美解决这个问题。 何 为异步调用?
@Configuration @EnableAsync public class SpringAsyncConfig { ... }
@SpringBootApplication@EnableAsyncpublic class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
@Async //标注使用public void downloadFile() throws Exception { ... }
@Async public Future asyncMethodWithReturnType() {
System.out.println("Execute method asynchronously - " + Thread.currentThread().getName()); try {
Thread.sleep(5000); return new AsyncResult("hello world !!!!");
} catch (InterruptedException e) { //
} return null;
}
以上示例可以发现,返回的数据类型为Future类型,其为一个接口。具体的结果类型为AsyncResult,这个是需要注意的地方。 调用返回结果的异步方法示例:
public void testAsyncAnnotationForMethodsWithReturnType()
throws InterruptedException, ExecutionException {
System.out.println("Invoking an asynchronous method. " + Thread.currentThread().getName());
Future future = asyncAnnotationExample.asyncMethodWithReturnType(); while (true) { ///这里使用了循环判断,等待获取结果信息 if (future.isDone()) { //判断是否执行完毕
System.out.println("Result from asynchronous process - " + future.get()); break;
}
System.out.println("Continue doing something else. ");
Thread.sleep(1000);
}
}
这些获取异步方法的结果信息,是通过不停的检查Future的状态来获取当前的异步方法是否执行完毕来实现的。 基 于@Async调用中的异常处理机制
public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor { private AsyncTaskExecutor executor; public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) { this.executor = executor;
} 用独立的线程来包装,@Async其本质就是如此 public void execute(Runnable task) {
executor.execute(createWrappedRunnable(task));
} public void execute(Runnable task, long startTimeout) {
/用独立的线程来包装,@Async其本质就是如此
executor.execute(createWrappedRunnable(task), startTimeout);
} public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task)); //用独立的线程来包装,@Async其本质就是如此。
} public Future submit(final Callable task) { //用独立的线程来包装,@Async其本质就是如此。 return executor.submit(createCallable(task));
} private Callable createCallable(final Callable task) { return new Callable() { public T call() throws Exception { try { return task.call();
} catch (Exception ex) {
handle(ex); throw ex;
}
}
};
} private Runnable createWrappedRunnable(final Runnable task) { return new Runnable() { public void run() { try {
task.run();
} catch (Exception ex) {
handle(ex);
}
}
};
} private void handle(Exception ex) { //具体的异常逻辑处理的地方
System.err.println("Error during @Async execution: " + ex);
}
}
分析:可以发现其是实现了AsyncTaskExecutor, 用独立的线程来执行具体的每个方法操作。在createCallable和createWrapperRunnable中,定义了异常的处理方式和机制。
handle()
就是未来我们需要关注的异常处理的地方。 xml配置文件中的内容:
bean>
也可以使用注解的形式将其配置注册到bean中。 注 @Async调用中的事务处理机制 在
@Async
标注的方法,同时也使用
@Transactional
进行标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。 那该如何给这些操作添加事务管理呢? 可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加
@Transactional
@Async
/
@Transactional
来标注,但是无法产生事务控制的目的。
方法B, 使用了
@Async
来标注,B中调用了C、D,C/D分别使用
@Transactional
做了标注,则可实现事务控制的目的。
参 参考文章:
[1]https://www.cnblogs.com/wihainan/p/6516858.html
[2]http://www.cnblogs.com/wihainan/p/6098970.html
近期精彩内容推荐:
知乎高赞:高考700分和700万怎么选?
Python这五个坑,怎么避开?
贼好用的Java工具类库,GitHub星标10k+
“新冠牌”啤酒真倒霉:60天赔了20个亿
