Spring中@Async

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题

 

1.  何为异步调用?

    在解释异步调用之前,我们先来看同步调用的定义;同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。

     例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕; 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。

 

2.  常规的异步调用处理方式

    在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。或是使用TaskExecutor执行异步线程,参看http://www.cnblogs.com/wihainan/p/6098970.html。

 

3. @Async介绍

   在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。

   如何在Spring中启用@Async。基于Java配置的启用方式:

1 @Configuration  
2 @EnableAsync  
3 public class SpringAsyncConfig { ... }  

 

4. 基于@Async无返回值调用

使用的方式非常简单,一个标注即可解决所有的问题:

1 @Async  //标注使用  
2 public void asyncMethodWithVoidReturnType() {  
3     System.out.println("Execute method asynchronously. "  
4       + Thread.currentThread().getName());  
5 }  

5. 基于@Async返回值的调用

 1 @Async  2 public Future<String> asyncMethodWithReturnType() {  3     System.out.println("Execute method asynchronously - "  + Thread.currentThread().getName());  4     try {  5         Thread.sleep(5000);  6         return new AsyncResult<String>("hello world !!!!");  7     } catch (InterruptedException e) {  8         //  9     }  
10    
11     return null;  
12 }  

  以上示例可以发现,返回的数据类型为Future类型,其为一个接口。具体的结果类型为AsyncResult,这个是需要注意的地方。

 调用返回结果的异步方法示例

 1 public void testAsyncAnnotationForMethodsWithReturnType()  2    throws InterruptedException, ExecutionException {  3     System.out.println("Invoking an asynchronous method. "   + Thread.currentThread().getName());  4     Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();  5    6     while (true) {  ///这里使用了循环判断,等待获取结果信息  7         if (future.isDone()) {  //判断是否执行完毕  8             System.out.println("Result from asynchronous process - " + future.get());  9             break;  
10         }  
11         System.out.println("Continue doing something else. ");  
12         Thread.sleep(1000);  
13     }  
14 }  

这些获取异步方法的结果信息,是通过不停的检查Future的状态来获取当前的异步方法是否执行完毕来实现的。

 

6. 基于@Async调用中的异常处理机制

 在异步方法中,如果出现异常,对于调用者caller而言,是无法感知的。如果确实需要进行异常处理,则按照如下方法来进行处理:

    1.  自定义实现AsyncTaskExecutor的任务执行器

         在这里定义处理具体异常的逻辑和方式。

    2.  配置由自定义的TaskExecutor替代内置的任务执行器

    示例步骤1,自定义的TaskExecutor

 

 1 public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor {  2     private AsyncTaskExecutor executor;  3     public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) {  4         this.executor = executor;  5      }  6       用独立的线程来包装,@Async其本质就是如此  7     public void execute(Runnable task) {       8       executor.execute(createWrappedRunnable(task));  9     }  
10     public void execute(Runnable task, long startTimeout) {  
11         /用独立的线程来包装,@Async其本质就是如此  
12        executor.execute(createWrappedRunnable(task), startTimeout);           
13     }   
14     public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task));  
15        //用独立的线程来包装,@Async其本质就是如此。  
16     }   
17     public Future submit(final Callable task) {  
18       //用独立的线程来包装,@Async其本质就是如此。  
19        return executor.submit(createCallable(task));   
20     }   
21       
22     private Callable createCallable(final Callable task) {   
23         return new Callable() {   
24             public T call() throws Exception {   
25                  try {   
26                      return task.call();   
27                  } catch (Exception ex) {   
28                      handle(ex);   
29                      throw ex;   
30                    }   
31                  }   
32         };   
33     }  
34   
35     private Runnable createWrappedRunnable(final Runnable task) {   
36          return new Runnable() {   
37              public void run() {   
38                  try {  
39                      task.run();   
40                   } catch (Exception ex) {   
41                      handle(ex);   
42                    }   
43             }  
44         };   
45     }   
46     private void handle(Exception ex) {  
47       //具体的异常逻辑处理的地方  
48       System.err.println("Error during @Async execution: " + ex);  
49     }  
50 }

 分析: 可以发现其是实现了AsyncTaskExecutor, 用独立的线程来执行具体的每个方法操作。在createCallable和createWrapperRunnable中,定义了异常的处理方式和机制。

 handle()就是未来我们需要关注的异常处理的地方。 配置文件中的内容:

1 <task:annotation-driven executor="exceptionHandlingTaskExecutor" scheduler="defaultTaskScheduler" />  
2 <bean id="exceptionHandlingTaskExecutor" class="nl.jborsje.blog.examples.ExceptionHandlingAsyncTaskExecutor">  
3     <constructor-arg ref="defaultTaskExecutor" />  
4 </bean>  
5 <task:executor id="defaultTaskExecutor" pool-size="5" />  
6 <task:scheduler id="defaultTaskScheduler" pool-size="1" />  

 

7. @Async调用中的事务处理机制

    在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。

     那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.

    例如:  方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。

          方法B,使用了@Async来标注,  B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。

不积跬步无以至千里

转载于:https://www.cnblogs.com/zhangwufei/p/10036401.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/570113.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql不能停用

Timeout error occurred trying to start MySQL Daemon.Starting MySQL: [FAILED]

CentOs如何挂载硬盘

远程SSH登录上Centos服务器后&#xff0c;进行如下操作提醒&#xff1a;挂载操作会清空数据&#xff0c;请确认挂载盘无数据或者未使用第一步&#xff1a;列出所有磁盘 命令&#xff1a; ll /dev/disk/by-path 提示&#xff1a;如果无法确认数据盘设备名称&#xff0c;请使…

挂载

df -Th 查看磁盘挂载情况 ls /dev/sdx* fdisk -l 查看分区情况 fdisk /dev/sdb 分区mnpw uuid:设备的唯一号 blkidUUID"0a59654a-6f2c-4bc1-bbaf-df844e60e2e3" UUID"fe8c9dd4-571c-40a4-837a-a4ab6e4ae7e转载于:https://www.cnblogs.com/finddata/p/10041496.h…

一周冲刺计划2//第一天

第二次一周冲刺计划 2018.12.1 今天开展了小组间的站立会议&#xff0c;四个人仔细分析了第一次冲刺计划中软件的不足&#xff0c;对其的不足之处进行了深刻的反省和分析&#xff0c;并做出相应的修改。首先做出UI界面&#xff0c;对界面进行修改。明天对代码进行修改。转载于:…

linux版的navicat提示丢失scilexer.dll

这是由于SELinux阻止了scilexer.dll加载 &#xff0c;只要解除阻止就可以了。命令解除&#xff1a;如果SELinux是处于强制安全模式时需要做getenforce令SELinux处于容许模式setenforce 0chcon -t textrel_shlib_t scilexer.dll的路径

AWS EC2实例Ubuntu系统设置root用户密码并使用root/ubuntu用户登录

参考链接&#xff1a;http://www.wangchao.info/1137.html 注意&#xff1a;链接中写的简化了&#xff0c;其中重启服务的命令似乎不太适用&#xff0c;可能是不通用&#xff0c;我下面描述的方式亲测可行&#xff0c;如有其他疑问请留言&#xff1b; https://blog.csdn.net/p…

最全的纯净系统下载地址

http://msdn.itellyou.cn/?langzh-cn

坑题

题目描述 小姐姐想要配 n 把钥匙&#xff0c;她走过开锁铺问老板价钱&#xff0c;老板是这么说的&#xff1a; 小姐姐想知道完成配n把钥匙的任务最少需要花费多少钱 输入描述: 题目有多组测试数据。第一行输入一个整数T&#xff08;组数少于100组&#xff09;&#xff0c;表示测…

windows 下架设svn服务器

一、准备工作1、获取 Subversion 服务器程序 到官方网站&#xff08;http://www.collab.net/downloads/subversion &#xff09;下载最新的服务器安装程序。目前最新的是1.7.7版本. 2、获取 TortoiseSVN 客户端程序从官方网站 http://tortoisesvn.net/downloads 获取最新的 To…

最简单的nginx教程 - 如何把一个web应用部署到nginx上

Nginx (engine x) 是一个高性能的HTTP和反向代理服务&#xff0c;也是一个IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的&#xff0c;第一个公开版本0.1.0发布于2004年10月4日…

Linux下tomcat的配置

1、安装JDK文件双击jdk-6u33-linux-x64.bin&#xff0c;以以终端方式运行&#xff0c;安装在opt文件夹下在root用户 下&#xff0c;首先添加执行权限代码 chmod x jdk-6u29-linux-i586-rpm.bin 然后执行 ./jdk-6u29-linux-i586-rpm.bin 2.将tomcat解压出来&#xff0c;放在…

修理牧场(哈夫曼树 )

农夫要修理牧场的一段栅栏&#xff0c;他测量了栅栏&#xff0c;发现需要N块木头&#xff0c;每块木头长度为整数L​i​​个长度单位&#xff0c;于是他购买了一条很长的、能锯成N块的木头&#xff0c;即该木头的长度是L​i​​的总和。 但是农夫自己没有锯子&#xff0c;请人锯…

修改FTP服务器端口后无法访问

如果将FTP服务器原先的端口21修改成其他的端口号&#xff0c;那么访问FTP服务器的方式只能是主动访问如果是用浏览器&#xff0c;那么设置如下&#xff1a;打开浏览器&#xff0c;找到“菜单栏”——“工具”——“Internet 选项” ——“高级”&#xff0c;会看到“使用被动FT…

Median(二分+二分)

Median http://poj.org/problem?id3579 Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 11225 Accepted: 4016Description Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i &#xff1c; j …

VNCServer在Linux下设置

1.检查vnc客户端和服务器是否已经安装&#xff1a; [rootcentos ~]$ rpm -q vnc-server package vnc-server is not installed 说明没有安装 运行yum install vnc-server进行安装 vnc-server-4.0-8.1 说明安装已经安装了 只是没开启服务而已 2. 将用户名称加入到配置…

Judy alpha 第七天

SCRUM 今天 debugger 部分由 Yu Xing 继续完成断点功能&#xff0c;由 Zhiqi Lin 开始实现查看变量功能。项目整体打包测试仍有困难&#xff0c;VS Code extension 的文档质量不佳&#xff0c;大家感到难以调试。成员昨日进展今日任务Zibo Wang协助打包、追踪开发进度协助打包、…

c++教程下载

孙鑫C视频教程 rmvb格式 全20CD完整版http://bbs.topsage.com/dispbbs.asp?boardID121&ID156290C视频教程 边用边学Visual C 6 (ASF格式)http://bbs.topsage.com/dispbbs.asp?boardID121&ID177500中山大学蔡培兴 C语言视频教程 全51讲 精品推荐 http://bbs.topsage.c…

Phaser3让超级玛丽实现轻跳、高跳及加上对应的跳跃声音

mario jumper在线测试地址&#xff1a;http://www.ifiero.com/uploads/phaserjs3/jumper/ 空格键&#xff1a;轻按&#xff1a;跳低 &#xff0c;长按&#xff1a;跳高键盘&#xff1a;--> 向右 , <-- 向左 请确保已打开电脑的音乐开关 var config {type: Phaser.AUTO,w…

linux下文件删除不了

在linux系统下当删除文件时提示无法操作&#xff0c;有可能是文件被使用了chattr改变了属性。可以使用lsattr命令来查看 [rootlinux236 root]# lsattr   ---i---------- ./1.txt   -------------- ./weiqi.ldif -------------- ./qi.schema 以上可以看出1.txt文件被添加了…

struts2配置问题

struts2.2.1之后的版本除了commons-fileupload-1.3、commons-io-2.2、freemarker-2.3.19、javassist-3.11.0.GA、ognl-3.0.6、struts2-core-2.3.16、xwork-core-2.3.16之外&#xff0c;还需要commons-lang3-3.1才能正常运行