专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  这 30 款 IDEA 宝贝插件 yyds ·  2 天前  
Java知音  ·  让数据传输更优雅:SpringBoot前后端 ... ·  5 天前  
芋道源码  ·  Redission 分布式锁原理分析 ·  5 天前  
Java编程精选  ·  某大厂员工自曝:很难想象,我拿年薪70w的工 ... ·  1 周前  
51好读  ›  专栏  ›  ImportNew

Java 异步编程最佳实践

ImportNew  · 公众号  · Java  · 2017-02-11 20:16

正文

(点击上方公众号,可快速关注)


来源:colobu,

colobu.com/2015/03/24/Best-Practices-of-Asynchronous-Programming-With-Java/

如有好文章投稿,请点击 → 这里了解详情


什么是异步?为什么要用它?


异步编程提供了一个非阻塞的,事件驱动的编程模型。 这种编程模型利用系统中多核执行任务来提供并行,因此提供了应用的吞吐率。此处吞吐率是指在单位时间内所做任务的数量。 在这种编程方式下, 一个工作单元将独立于主应用线程而执行, 并且会将它的状态通知调用线程:成功,处理中或者失败。


我们需要异步来消除阻塞模型。其实异步编程模型可以使用同样的线程来处理多个请求, 这些请求不会阻塞这个线程。想象一个应用正在使用的线程正在执行任务, 然后等待任务完成才进行下一步。 log框架就是一个很好的例子:典型地你想将异常和错误日志记录到一个目标中, 比如文件,数据库或者其它类似地方。你不会让你的程序等待日志写完才执行,否则程序的响应就会受到影响。 相反,如果对log框架的调用是异步地,应用就可以并发执行其它任务而无需等待。这是一个非阻塞执行的例子。


为了在Java中实现异步,你需要使用Future 和 FutureTask, 它们位于java.util.concurrent包下. Future是一个接口而FutureTask是它的一个实现类。实际上,如果在你的代码中使用Future, 你的异步任务会立即执行, 并且调用线程可以得到结果promise。


下面的代码片段定义了一个包含两个方法的接口。 一个是同步方法,另外一个是异步方法。


import java.util.concurrent.Future;

public interface IDataManager {

   // synchronous method

   public String getDataSynchronously();

   // asynchronous method

   public Future getDataAsynchronously();

}


值得注意的是回调模型的弊端就是当回调嵌套时很麻烦。


该做和不该做的


为了方便测试, 你应该在代码中将功能从多线程中隔离出来。当在Java中编写异步代码时,你应该遵循异步模型,这样调用线程就不会被阻塞。


注意构造函数不能是异步的,你不应该在构造函数中调用异步方法。当任务互相不依赖时异步方式尤其有用。当调用任务依赖被调用任务时不应该使用异步(译者按:这对异步来说无意义,因为业务上调用线程被阻塞了).


你应该在异步方法中处理异常. 你不应该为长时间的task实现异常. 一个长时间运行的任务,如果异步执行的话, 可能会比同步执行耗费更长的时间, 因为运行时要为异步执行的方法执行线程上下文的切换, 线程状态的存储等. 你也应该注意同步的异常和异步的异常有所不同。 同步异常暗示 每次程序执行到那个程序特殊状态时就会抛出异常;异步异常的跟踪则困难的多。所以同步和异步异常暗示同步或异步代码可能抛出异常(synchronous and asynchronous exceptions imply synchronous or asynchronous code in your program that might raise exceptions.)。


推荐阅读


  1. https://msdn.microsoft.com/en-us/magazine/dn818494.aspx


  2. http://docs.oracle.com/javaee/6/tutorial/doc/gkiez.html


  3. https://technology.amis.nl/2009/02/19/asynchronous-processing-in-java-applications-leveraging-those-multi-cores/


  4. http://javarevisited.blogspot.in/2015/01/how-to-use-future-and-futuretask-in-Java.html


  5. http://www.codeproject.com/Articles/562021/Asynchronous-models-and-patterns


总结


异步对于设计大规模快速响应的应用是至关重要的。异步回调模型带来了很多的好处;你可以依赖你的异步回调方法来执行昂贵的I/O操作而你的处理器可以执行其它任务。然而虽然在Java和C#中提供了异步的支持,异步编程并不总是那么容易实现。异步方式的使用要谨慎: 你应该清楚什么时候可以用和什么时候不该用。


本文中我们介绍了异步编程的概念, 以及使用Java编程需要怎么去实现. 本文也列出了使用异步编程的最佳实践。谢谢阅读。


译者增加的内容


Java 7中提供了Fork/Join框架, 可以将一个大的task分割成很多可以并行执行的小task。Java 8中parallelStream内部利用Fork/Join执行并发操作。


Reactive Extensions for .NET提供了异步和基于事件编程框架, Java中对应的是Netflix的RxJava,你可以使用它实现CQRS和Event Sourcing模式。


Akka提供了一个分布式的,容错的,事件驱动的框架, 可以实现异步的分布式的编程。


还有Spring的reactor也提供了高性能的事件驱动的异步框架。


像Node.js天生支持异步编程模式, 其它语言如golang使用 goroutines 和 channels.也很容易实现异步。


觉得本文对你有帮助?请分享给更多人

关注「ImportNew」,提升Java技能