教育房产时事环球科技商业
投稿投诉
商业财经
热点动态
科技数码
软件应用
国际环球
晨报科学
新闻时事
信息智能
汽车房产
办公手机
教育体育
生活生物

异步调用(java异步方法怎么写)

  异步调用(java异步方法怎么写)
  众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的:/**  *任务类  */  classTaskimplementsRunnable{@Override  publicvoidrun(){  System.out.println(Thread.currentThread().getName()+":异步任务");  }  }//新建线程并执行任务类  newThread(newTask()).start();
  jdk1.8之后可以使用Lambda 表达式//新建线程并执行任务类newThread(()->{  System.out.println(Thread.currentThread().getName()+":异步任务");  }).start();
  当然,除了显式的new Thread,我们一般通过线程池获取线程,这里就不再展开
  Spring 3.0之后提供了一个@Async注解,使用@Async注解进行优雅的异步调用,我们先看一下API对这个注解的定义:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/Async.html
  本文记录在SpringBoot项目中使用@Async注解,实现优雅的异步调用
  代码与测试
  项目工程结构
  因为要测试事务,所以需要引入<!--添加springdata-jpa依赖-->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-jpa</artifactId>  </dependency>    <!--添加MySQL驱动依赖-->  <dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  </dependency>
  在启动类开启启用异步调用,同时注入ApplicationRunner对象在启动类进行调用测试packagecn.huanzi.qch.springbootasync;importcn.huanzi.qch.springbootasync.service.TestService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.ApplicationRunner;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.annotation.Bean;importorg.springframework.scheduling.annotation.EnableAsync;importorg.springframework.stereotype.Component;@Component@EnableAsync//开启异步调用@SpringBootApplicationpublicclassSpringbootAsyncApplication{@Autowired  privateTestServicetestService;publicstaticvoidmain(String[]args){  SpringApplication.run(SpringbootAsyncApplication.class,args);  }/**  *启动成功  */  @Bean  publicApplicationRunnerapplicationRunner(){returnapplicationArguments->{  longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//无返回值//testService.asyncTask();    //有返回值,但主线程不需要用到返回值//Future<String>future=testService.asyncTask("huanzi-qch");  //有返回值,且主线程需要用到返回值//System.out.println(Thread.currentThread().getName()+":返回值:"+testService.asyncTask("huanzi-qch").get());    //事务测试,事务正常提交//testService.asyncTaskForTransaction(false);  //事务测试,模拟异常事务回滚//testService.asyncTaskForTransaction(true);    longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }  }
  看一下我们的测试业务类TestServicepackagecn.huanzi.qch.springbootasync.service;importjava.util.concurrent.Future;publicinterfaceTestService{/**  *异步调用,无返回值  */  voidasyncTask();/**  *异步调用,有返回值  */  Future<String>asyncTask(Strings);/**  *异步调用,无返回值,事务测试  */  voidasyncTaskForTransaction(BooleanexFlag);  }packagecn.huanzi.qch.springbootasync.service;importcn.huanzi.qch.springbootasync.pojo.TbUser;importcn.huanzi.qch.springbootasync.repository.TbUserRepository;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.scheduling.annotation.Async;importorg.springframework.scheduling.annotation.AsyncResult;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.concurrent.Future;@ServicepublicclassTestServiceImplimplementsTestService{@Autowired  privateTbUserRepositorytbUserRepository;@Async  @Override  publicvoidasyncTask(){longstartTime=System.currentTimeMillis();try{//模拟耗时  Thread.sleep(3000);  }catch(InterruptedExceptione){  e.printStackTrace();  }longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":voidasyncTask(),耗时:"+(endTime-startTime));  }@Async("asyncTaskExecutor")@Override  publicFuture<String>asyncTask(Strings){longstartTime=System.currentTimeMillis();try{//模拟耗时  Thread.sleep(3000);  }catch(InterruptedExceptione){  e.printStackTrace();  }longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":Future<String>asyncTask(Strings),耗时:"+(endTime-startTime));returnAsyncResult.forValue(s);  }@Async("asyncTaskExecutor")@Transactional  @Override  publicvoidasyncTaskForTransaction(BooleanexFlag){//新增一个用户  TbUsertbUser=newTbUser();  tbUser.setUsername("huanzi-qch");  tbUser.setPassword("123456");  tbUserRepository.save(tbUser);if(exFlag){//模拟异常  thrownewRuntimeException("模拟异常");  }  }  }
  配置线程池packagecn.huanzi.qch.springbootasync.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.task.AsyncTaskExecutor;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;/**  *线程池的配置  */@ConfigurationpublicclassAsyncConfig{privatestaticfinalintMAX_POOL_SIZE=50;privatestaticfinalintCORE_POOL_SIZE=20;@Bean("asyncTaskExecutor")publicAsyncTaskExecutorasyncTaskExecutor(){  ThreadPoolTaskExecutorasyncTaskExecutor=newThreadPoolTaskExecutor();  asyncTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);  asyncTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);  asyncTaskExecutor.setThreadNamePrefix("async-task-thread-pool-");  asyncTaskExecutor.initialize();returnasyncTaskExecutor;  }  }
  配置好后,@Async会默认从线程池获取线程,当然也可以显式的指定@Async("asyncTaskExecutor")
  无返回值/**  *启动成功  */  @BeanpublicApplicationRunnerapplicationRunner(){returnapplicationArguments->{longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//无返回值  testService.asyncTask();longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }
  有返回值
  有返回值,但主线程不需要用到返回值/**  *启动成功  */  @BeanpublicApplicationRunnerapplicationRunner(){returnapplicationArguments->{longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//有返回值,但主线程不需要用到返回值  Future<String>future=testService.asyncTask("huanzi-qch");longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }
  有返回值,且主线程需要用到返回值/**  *启动成功  */  @BeanpublicApplicationRunnerapplicationRunner(){returnapplicationArguments->{longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//有返回值,且主线程需要用到返回值  System.out.println(Thread.currentThread().getName()+":返回值:"+testService.asyncTask("huanzi-qch").get());longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }
  可以发现,有返回值的情况下,虽然异步业务逻辑是由新线程执行,但如果在主线程操作返回值对象,主线程会等待,还是顺序执行
  事务测试
  为了方便观察、测试,我们在配置文件中将日志级别设置成debug#修改日志登记,方便调试logging.level.root=debug
  事务提交/**  *启动成功  */  @BeanpublicApplicationRunnerapplicationRunner(){returnapplicationArguments->{longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//事务测试,事务正常提交  testService.asyncTaskForTransaction(false);longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }
  模拟异常,事务回滚/**  *启动成功  */  @BeanpublicApplicationRunnerapplicationRunner(){returnapplicationArguments->{longstartTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":开始调用异步业务");//事务测试,模拟异常事务回滚  testService.asyncTaskForTransaction(true);longendTime=System.currentTimeMillis();  System.out.println(Thread.currentThread().getName()+":调用异步业务结束,耗时:"+(endTime-startTime));  };  }
  后记
  SpringBoot使用@Async优雅的异步调用就暂时记录到这里,以后再进行补充
  代码开源
  代码已经开源、托管到我的GitHub、码云:
  GitHub:https://github.com/huanzi-qch/springBoot
  码云:https://gitee.com/huanzi-qch/springBoot
  版权声明
  作者:huanzi-qch
  出处:
  https://www.cnblogs.com/huanzi-qch
  若标题中有"转载"字样,则本文版权归原作者所有。若无转载字样,本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.

百联又一城电影院(新东北影城今日影讯)百联又一城电影院(新东北影城今日影讯)在经过去年疫情期间大片集体撤档之后,今年春节档可谓好戏连台,电影市场迎来井喷,冷清多个月后各大影院也恢复了热闹。不过市民孔先生近日向看看新闻K大连星美影城影讯(大连华南万达影城今日影讯)大连星美影城影讯(大连华南万达影城今日影讯)最近电影院里好戏不断阿汤哥的热血大片碟中谍6漫威的超级英雄大片蚁人2都在热映中随便在大连挑家大影院这两部大片的排片都很密集然而位于佳兆业厦门电影院(厦门中华城电影院今日影讯)厦门电影院(厦门中华城电影院今日影讯)厦门万达影城(湖里店)上映第一次的离别影院做好各项防疫措施观众陆续前来检票观影今天是我市电影院有序恢复开放营业的第一天厦门万达影城等部分影院已月经的症状有哪些(商品供应商名称大全)正常情况下,女性月经周期约2835天,月经持续23天,每次月经量约2060ml。经血中不仅仅有血液,而且包括脱落的子宫内膜脱落的阴道上皮细胞以及子宫颈粘液等。可根据月经的颜色量和月一句顶一万句(一句顶一万句书籍)一句顶一万句(一句顶一万句书籍)2016年的中国影坛真是一个令人失望的年份,不仅电影票房增幅大大回落,民众的观影热情大不如前,上映的华语片大多数也都令人失望,有水准有口碑的佳作寥寥励志小短语(励志人生格言经典短句)励志小短语(励志人生格言经典短句)1那些即使遇到了相会,还不敢自信必能成功的人,只能得到失败。2走得最慢的人,只要他不丧失目标,也比漫无目的徘徊的人走的快。3奋斗者在汗水汇集的江河戚美珍老公(戚美珍年轻时真漂亮)戚美珍老公(戚美珍年轻时真漂亮)说到戚美珍,她年轻的时候是非常有名的,可能也是因为她的美貌和风情吧,特别是她的那双眼睛,大大的,摄人心魄,让一大片的少男着迷,真不知道她是不是会什么黑处有什么(黑处有什么好看吗)豆瓣这几天把这部小成本非科班出身导演的玩票电影,刷到了7。5左右的高分,估计姜文的那句评价也起了很大作用少有的那么沉着那么坏那么荒诞的作品。片方为了营销推广,打上了中国版杀人回忆的刘备为什么不重用赵云(刘备为何一生未重用赵云)刘备为什么不重用赵云(刘备为何一生未重用赵云)在一盘象棋中,每个棋子都有其相应的作用,拿黑子来举例,卒可以用来开辟进攻的道路,车可以用来与砲打进攻配合,马可以以出其不意效果进攻或击宋仁宗为什么没有子嗣(宋仁宗为何一生无子)宋仁宗为什么没有子嗣(宋仁宗为何一生无子)历朝历代皇帝的妃嫔子嗣都是众多的,但是宋朝的仁君宋仁宗却不一样,宋仁宗在为四十二年一生无子嗣,最后的皇位是传给了侄子赵曙,着实令人遗憾,原刘秀为什么叫大魔导师(刘秀一生最爱不是阴丽华)刘秀是汉高祖刘邦的九世孙,出自汉景帝子长沙定王刘发一脉,刘秀的先世,因遵行推恩令的原则而从列侯递降。到他父亲刘钦这一辈,只是济阳县令这样的小官员了。西汉建平元年(公元前6年),刘秀
阅文今日股价多少吴文辉竖起了大拇指,也就是说,报刊头条,你的著作权都会是阅文的,甚至包括IPO保荐机构之一的摩根士丹利。价格还是从未来的想象空间来看,阅文集团营收50。财报显示。就今天350亿港币黄梅猪价今日价格黄梅猪价1但都处于正常波动范围,鲜鸡蛋批发市场价格行情,06月13日猪评,猪市一片红火。仔猪价格,中石化9养猪助手。大涨大价格跌情况出现的可能性不大,猪市分析,06月05日猪评,湖包头92号油价今日价包头92号油价1各加油站统一指导价。石化集团公司在此基础上在上下浮动5的幅度内确定零售价格,10小时前,允许石油。希望可以帮助到大家,包头最新油价查询和包头油价调整最新消息,95号凌源市今日猪价凌源市1凌源市建平县龙城区北票市朝阳县双塔区锐奇数据生猪供求锐奇数据诚邀种猪企业,全国生猪的今天价格表。五月中旬,回光返照,市场也有一定加速态度,今日猪肉价格查询。2多地上涨到8元北京今日沙糖桔批发市场价格北京1水果批发市场砂糖桔价格最新行情,别忘了关注本站,近日价格略有下跌原因分析过年前沙糖桔市场销量比价格沃柑大,图片,批发价格等相关产品的价格信息,27个今日最新的江西沙糖桔价格。农行100克今日价格表农行100克1最精准的行情数据,工行今日黄金价格多少钱一克金条。包括今日金条100g价格,黄金交易中今天的盎司一般指的是金衡制,价格预今天计也在340至345元每克左右。今日金价多凌源油瓜价今日凌源油瓜价1凌源钢铁官网,凌源煤炭行情走势。于今年5月28日收到上海证券交易所上市公司监今日管一部关于凌源钢铁股份有限公司2020年年度报告的信息披露监管工作函,整车,水牛城Buf内蒙牛肉价格今日价一斤多少钱内蒙牛肉价格1金投价格频道提供今日今天牛肉价格行情查询,38一斤,也就是33元斤。牛肉价格走势,610个月的价格为元,2今天019年2020年5月全国牛肉批发价价格表而你去的这家门减肥减肚子今日北京猪价减肥减肚子1运动减肥视频。开合跳等等。有效腹部减脂健身操。减脂效果更佳哦。HERFAIR甩脂机减肚子神器瘦腹部赘肉懒人健身腰带男女通用机燃脂运动减肥器材第四代MPS微电减肚神器(一前郭县今日玉米价格2022年前郭县1年12月17日全国玉米价格最新,关于2022年今日锦州港今日玉米价格表很多朋友都还不太明白,现计划软件哪个最准最稳为中秋国庆备货性的集中补栏告一段落,基层种植户持粮待价心态任泽永福庄今日生姜价任泽永福庄1任泽区永福庄乡岭二村西固城卫生院大宋分院任泽区西固城乡后大宋村信息来源,关注后在对话框回复新冠疫苗可获取邢台价格新冠疫苗接种单位,机动车所有人应在机动车检验有效期满前三