说说Java异步调用的几种方式

网友投稿 435 2022-10-08


说说Java异步调用的几种方式

目录一、通过创建新线程二、通过线程池三、通过@Async注解四、通过CompletableFuture

日常开发中,会经常遇到说,前台调服务,然后触发一个比较耗时的异步服务,且不用等异步任务的处理结果就对原服务进行返回。这里就涉及的java异步调用的一个知识。下面本文尝试将Java异步调用的多种方式进行归纳。

一、通过创建新线程

首先的我们得认识到,异步调用的本质,其实是通过开启一个新的线程来执行。如以下例子:

public static void main(String[] arghttp://s) throws Exception{

System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

new Thread(() -> {

System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());

try{

Thread.sleep(5000);

}catch (InterruptedException e){

e.printStackTrace();

}

System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());

}).start();

Thread.sleep(2000);

System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

数据结果如下所示,我们知道,System.currentTimeMillis()时间单位为ms。

主线程 =====> 开始 =====> 1627893837146

异步线程 =====> 开始 =====> 1627893837200

主线程 =====> 结束 =====> 1627893839205

异步线程 =====> 结束 =====> 1627893842212

我们通过线程休眠来达成主线程执行时间2秒左右,异步线程执行5秒左右的效果。通过打印出来的时间戳倒数第四位(秒位)我们可以看出,两个的线程执行总时间为5秒左右,符合异步执行的特征

以上是采用Runable实现多线程创建方式的lambda写法,关于的lambda知识,可参考Java Lambda 表达式;而关于多线程的多种实现方式,Java多线程事务管理一文有提及,可移步查看

二、通过线程池

因为异步任务的实现本质的由新线程来Lwusscqx执行任务,所以通过线程池的也可以实现异步执行。写法同我们利用线程池开启多线程一样。但由于我们的目的不是执行多线程,而是异步执行任务,所以一般需要另外一个线程就够了。

因此区别于执行多线程任务的我们常用的newFixedThreadPool,在执行异步任务时,我们用newSingleThreadExecutor 来创建一个单个线程的线程池。

public static void main(String[] args) throws Exception{

System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.submit(()->{

System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());

try{

Thread.sleep(5000);

}catch (InterruptedException e){

e.printStackTrace();

}

System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());

});

executorService.shutdown(); // 回收线程池

Thread.sleep(2000);

System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

执行结果如下:

主线程 =====> 开始 =====> 1627895467578

异步线程 =====> 开始 =====> 1627895467635

主线程 =====> 结束 =====> 1627895469644

异步线程 =====> 结束 =====> 1627895472649

可以看到,结果跟第一种结果是基本一致的。

温馨提示:不要忘记线程池的回收

三、通过@Async注解

我们都知道,SpringBoot项目有一个的很重要的特点就是的注解化。如果你的项目是SpringBoot,那就又多了一种选择——@Async注解。

使用起来也非常简单,将要异步执行的代码封装成一个方法,然后用@Async注解该方法,然后在主方法中直接调用就行。

@Test

public void mainThread() throws Exception{

System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

collectionBill.asyncThread();

Thread.sleep(2000);

System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

Thread.sleep(4000); // 用于防止jvm停止,导致异步线程中断

http://}

@Async

public void asyncThread(){

System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());

trhttp://y{

Thread.sleep(5000);

}catch (InterruptedException e){

e.printStackTrace();

}

System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());

}

执行结果如下:

主线程 =====> 开始 =====> 1627897539948

异步线程 =====> 开始 =====> 1627897539956

主线程 =====> 结束 =====> 1627897541965

异步线程 =====> 结束 =====> 1627897544966

有以下两点需要注意:

类似@Tranctional注解,@Async注解的方法与调用方法不能在同一个类中,否则不生效

JUnit框架的设计不考虑多线程场景,所以主线程退出后,子线程也会跟着立即退出,所以可以在后面加多线程休眠时间来观察异步线程的执行情况

四、通过CompletableFuture

CompletableFuture是JDK1.8的新特性,是对Future的扩展。CompletableFuture实现了CompletionStage接口和Future接口,增加了异步回调、流式处理、多个Future组合处理的能力。

实现代码如下:

public static void main(String[] args) throws Exception{

System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

ExecutorService executorService = Executors.newSingleThreadExecutor();

CompletableFuture.runAsync(() ->{

System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());

try{

Thread.sleep(5000);

}catch (InterruptedException e){

e.printStackTrace();

}

System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());

},executorService);

executorService.shutdown(); // 回收线程池

Thrhttp://ead.sleep(2000);

System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

同样可以实现类似的结果如下:

主线程 =====> 开始 =====> 1627898354914

异步线程 =====> 开始 =====> 1627898354977

主线程 =====> 结束 =====> 1627898356980

异步线程 =====> 结束 =====> 1627898359979

CompletableFuture有者非常强大的功能,能给我们带来非常丝滑的编程体验。后续会写一篇文章来详细介绍CompletableFuture


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:hacker之眼Nmap的原理及用法(三)绕过防火墙扫描的简单方法TCP ACK Ping
下一篇:信息时代的数据安全:RPA安全使用指南(rpa 网络安全)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~