Java线程中有单线程以及多线程,每种线程都着重要作用,而在实际开发中,有时候我们也需要使用java单线程实现异步操作,那java单线程如何实现异步?下面来我们就来给大家讲解一下。
因为异步任务的实现本质的由新线程来执行任务,所以通过线程池的也可以实现异步执行。写法同我们利用线程池开启多线程一样。但由于我们的目的不是执行多线程,而是异步执行任务,所以一般需要另外一个线程就够了。
因此区别于执行多线程任务的我们常用的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
java异步如何处理?
异步流程处理的实现有很多方式,但是实际开发中常用的就那么几种,例如:
基于接口异步响应,常用在第三方对接流程;
基于消息生产和消费模式,解耦复杂流程;
基于发布和订阅的广播模式,常见系统通知
注:异步适用的业务场景,对数据实时性、强一致性的要求不高,异步处理的数据更多时候追求的是最终一致性。关于“最终一致性有空在给大家介绍”。
下面结合不同的开发场景简单介绍下各种方式的使用
与第三方对接 :
大致流程如下:
地服务发起请求,调用第三方服务接口;
请求包含业务参数,和成功或失败的回调地址;
第三方服务实时响应流水号,作为该调用的标识;
之后第三方服务处理请求,得到最终处理结果;
如果处理成功,回调本地服务的成功通知接口;
如果处理失败,回调本地服务的失败通知接口;
注:如果本地服务多次请求第三方服务,需要根据流水号判断该请求的状态,业务的状态设计也是极其复杂,要根据流水号和状态追溯整个流程的执行进度,避免错乱。(保证请求一致性,避免相同请求数据重复请求重复处理)
生产消费模式:
消息生成之后,写入Kafka/MQ队列 ;
消息处理方获取消息后,进行流程处理;
消息在中间件提供的队列中持久化存储 ;
消息发起方如果挂掉,不影响消息处理 ;
消费方如果挂掉,不影响消息生成;
注:基于这种消息中间件模式,完成业务解耦,提高系统吞吐量,是(分布式)架构中常用的方式。即使有多个消息消费方,也只会在一个消费方处理消息,这就是该模式的特点。
发布订阅模式:
提供一个消息传递频道channel;
多个订阅频道的客户端client;
消息通过PUBLISH命令发送给频道channel ;
客户端就会收到频道中传递的消息 ;
注:广播模式更注重通知下发,流程交互性不强。实际开发场景:运维总控系统,更新了某类服务配置,通知消息发送之后,相关业务线上的服务在拉取最新配置,更新到服务中。(Nacos使用的就是该种模式)
总之异步可以解耦业务间的流程关联,降低耦合度,并且还能避免雪崩,另外java异步有以上三种处理方法,大家可以按照以上方法自己操作一下,最后大家如果想要了解更多java入门知识,敬请关注奇Q工具网。
推荐阅读: