Java异步编程

2021/5/17 14:25:33

本文主要是介绍Java异步编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

异步编程是一个广泛的话题,已经被广泛讨论,但是软件工程师仍在寻找实现并将其集成到应用程序中的方法。

 

作为一名软件工程师,我发现自己对如何一次完成许多事情感到好奇,而且我相信我并不是唯一一个提出这个问题的人。每个人都渴望提高生产力,并希望从各种应用程序中获得同样的收益。 

将我们的注意力转移到Java异步上,我们将在本文中发现实现它的多种方法以及不同的用例。

同步与异步

同步(Sync)和异步(Async)编程可以在一个或多个线程中完成。两者之间的主要区别在于,使用同步编程时,我们可以一次执行一个任务,但是使用异步编程时,我们可以一次执行多个任务。例如: 

  • 同步: 
    • 单线程:我开始煮鸡蛋,煮熟后我再开始烤面包。我必须等待一个任务完成才能开始另一个任务。
    • 多线程:我开始煮鸡蛋,煮熟后我妈妈会烤面包。任务由不同的人员(线程)一个接一个地执行。
  • 异步:
    • 单线程:我将鸡蛋放入锅中开始煮并设置一个计时器,将面包放入烤箱开始烤并启动另一个计时器,完成后,我就可以吃了。在异步中,我不必等待一项任务完成就可以启动另一个任务。
    • 多线程:我雇了2位厨师,他们会为我煮鸡蛋并为我烤面包。他们可以同时执行此操作,而不必等待一个完成以使另一个开始。

与线程异步

在Java中实现异步的第一种方法是使用Runnable接口和Thread类,该类可从JDK 1.0中找到。任何类都可以实现Runnable并覆盖run()方法,或者可以扩展Thread并执行相同的操作。区别在于,当直接从Runnable调用run方法时,不会创建新线程,而是将在正在调用的线程上运行。但是,当我们执行thread.start()时,将创建一个新线程。

为了更好地管理JDK 1.5中的线程,我们可以找到执行器。它们使用不同的ThreadPool,因此使用它们是因为不需要手动创建线程。相反,我们可以指定它可以具有多少个线程,并且它将在应用程序的生存期内重用这些线程。

与未来不同步

run()是一个无效方法,它不能从线程返回任何结果,但是如果我们需要在与main不同的线程上进行计算的结果,则需要使用Callable接口。任务的响应无法立即获得,Callable在提交给ExecutorService时将返回Future对象。这个对象的承诺是,当我们的计算结束时,我们可以通过它获得结果,我们只需要在Future上调用get()即可。这不是async的好用法,因为get()会阻塞当前线程,直到响应可用为止。但是,有一种解决方法,可以使用future.isDone()方法连续检查计算是否结束,并且只有当此方法返回true时,get()才会返回结果。

与CompletableFuture异步

在JDK 1.8中,Future对象进行了升级,它成为一个CompletableFuture对象,该对象除了Future之外,还实现了CompletionStage。CompletionStage提供了许多方法来简化在不同线程和阶段中计算出的响应的使用。一些最常见的方法是Streams中的thenApply()与map ()类似,thenAccept()与foreach类似。获得CompletableFuture响应的方法有多种,其中一些方法是否在不同线程上运行任务,但是Future的一个共同点和额外功能是,用户可以在计算过程中处理异常,以便对其进行处理。

与@Async异步

实现异步的另一种方法是使用Spring Framework提供的注释@Async。用户只能在公共方法上使用它,而不能在定义它们的同一个类中调用这些方法。用Async注释的方法内部的任何代码都将在不同的线程中执行,并且可以为空或可以返回CompletableFuture。因此,这是创建CompletableFuture并为其提供运行方法的一种替代方法,但是为了能够使用此批注,还需要另一件事:配置类上的@EnableAsync。

春季活动

使用Spring Events进行异步实现是向前迈出的一步,它还提供了去耦功能,并且提供了一种无需更改现有功能即可轻松添加新功能的简便方法。需要三个元素:

  • 事件-可以使用扩展ApplicationEvent的任何对象
  • 发布者–一个将使用ApplicationEventPublisher bean发布事件的bean
  • 侦听器–一个具有@EventListener注释的方法的Bean,它将在接收到特定事件时协助定义要执行的任务

默认情况下,侦听器方法是同步执行的,但也可以通过添加@Async批注轻松地使其异步。

使侦听器异步的另一种方法是在配置中添加具有SimpleApplicationEventMulticaster的Bean,并为其分配TaskExecutor。放置好该bean时,无需使用@Async注释每个EventListener,并且所有事件将在不同的线程上处理。当我们不想错过某个方法上的@Async注释时,使用配置bean方法会很有帮助,但是请注意,这种方法将使所有事件处理,甚至框架事件都变得异步。使用注释将使我们能够选择将哪些事件同步处理以及将哪些异步处理。

微服务

在微服务级别,我们还可以进行同步或异步通信。它们之间的区别在于,如定义中所述,异步意味着我们不等待正在调用的服务的即时响应,而同步意味着我们等待响应。

微服务之间最流行的同步通信之一是使用REST调用完成的。对于异步通信,我们可以使用队列或主题。它们都包含消息,但是一个区别是,来自队列的消息只能由一个订户使用,而来自主题的消息可以由多个订户读取。

异步的优缺点

用户在将任务委托给另一个线程时应该考虑使用异步编程,因为这很耗时,或者他们不希望任务的结果影响应用程序的当前流程。这样,用户可以一次执行多项操作。通过使用异步用户,可以解耦任务和组件,从而提高应用程序的整体性能。

另外,用户应注意,在使用异步方法甚至编写测试的代码中,调试会稍微复杂一些,但这在选择解决方案时不应成为障碍。

最后一件事

线程与工人有关,异步与任务有关!

 



这篇关于Java异步编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程