Tips

书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code

注意,书中的有些代码里方法是基于Java 9 API中的,所以JDK 最好下载 JDK 9以上的版本。

80. EXECUTORS, TASKS, STREAMS 优于线程

本书的第一版包含一个简单工作队列的代码[Bloch01,条目 49]。 此类允许客户端将后台线程的异步处理工作排入队列。 当不再需要工作队列时,客户端可以调用一个方法,要求后台线程在完成队列中已有的任何工作后正常终止自身。 实现只不过是个玩具,但即便如此,它还需要一整页精细,细致的代码,如果你没有恰到好处的话,这种代码很容易出现安全和活性失败。 幸运的是,没有理由再编写这种代码了。

到本书第二版出版时,java.util.concurrent包已添加到Java中。 该包包含一个Executor Framework,它是一个灵活的基于接口的任务执行工具。 创建一个比本书第一版更好的工作队列只需要一行代码:

ExecutorService exec = Executors.newSingleThreadExecutor();

下面是如何提交一个可运行的(runnable)执行:

exec.execute(runnable);

下面是如何告诉executor优雅地终止(如果做不到这一点,你的虚拟机很可能不会退出):

exec.shutdown();

可以使用执行器服务(executor service)做更多的事情。例如,可以等待一个特定任务完成(条目 79中使用get方法, 319页),可以等待任何或全部任务完成的集合(使用invokeAny或invokeAll方法),也可以等待执行者服务终止(使用awaitTermination方法),可以在完成任务时逐个检索任务结果(使用ExecutorCompletionService),可以安排任务在特定时间运行或定期运行(使用ScheduledThreadPoolExecutor),等等。

如果希望多个线程处理来自队列的请求,只需调用另一个静态工厂,该工厂创建一种称为线程池的不同类型的执行器服务。 可以创建具有固定或可变数量线程的线程池。 java.util.concurrent.Executors类包含静态工厂,它们提供了你需要的大多数执行程序。 但是,如果想要一些与众不同的东西,可以直接使用ThreadPoolExecutor类。 此类允许你配置线程池操作的几乎每个方面。

为特定应用程序选择执行程序服务可能很棘手。 对于小程序或负载较轻的服务器,Executors.newCachedThreadPool通常是一个不错的选择,因为它不需要配置,通常“做正确的事情”。但是对于负载很重的生产服务器来说,缓存线程池不是一个好的选择! 在缓存线程池中,提交的任务不会排队,而是立即传递给线程执行。 如果没有可用的线程,则创建一个新线程。 如果服务器负载过重以至于所有CPU都被充分利用并且更多任务到达时,则会创建更多线程,这只会使事情变得更糟。 因此,在负载很重的生产服务器中,最好使用Executors.newFixedThreadPool,它提供具有固定线程数的池,或直接使用ThreadPoolExecutor类,以实现最大程度的控制。

不仅应该避免编写自己的工作队列,而且通常应该避免直接使用线程。 当直接使用Thread类时,线程既可以作为工作单元,也可以作为执行它的机制。 在executor framework中,工作单元和执行机制是分开的。 关键的抽象是工作单元,称为任务。 有两种任务:Runnable及其近亲Callable(类似于Runnable,除了它返回一个值并且可以抛出任意异常)。 执行任务的一般机制是executor service。 如果从任务的角度来看,让executor service为你执行它们,可以灵活地选择适当的执行策略以满足你的需求,并在需求发生变化时更改策略。 本质上本质上,Executor Framework执行的功能与Collections Framework聚合(aggregation)功能是相同的。

在Java 7中,Executor Framework被扩展为支持fork-join任务,这些任务由称为fork-join池的特殊executor service运行。 由ForkJoinTask实例表示的fork-join任务可以拆分为较小的子任务,而包含ForkJoinPool的线程不仅处理这些任务,而且还“彼此”窃取“任务”以确保所有线程都保持忙碌,从而导致更高的任务 CPU利用率,更高的吞吐量和更低的延迟。 编写和调优fork-join任务很棘手。 并行流(Parallel streams)(条目 48)是在fork-join池之上编写的,假设它们适合当前的任务,那么你可以轻松地利用它们的性能优势。

对Executor Framework的完整处理超出了本书的范围,但感兴趣的读者可以参考 《Java Concurrency in Practice》一书[Goetz06]。

Effective Java 第三版——80. EXECUTORS, TASKS, STREAMS 优于线程的更多相关文章

  1. Effective Java 第三版—— 85. 其他替代方式优于Java本身序列化

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  2. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  3. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  4. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——7. 消除过期的对象引用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——9. 使用try-with-resources语句替代try-finally语句

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  8. Effective Java 第三版——10. 重写equals方法时遵守通用约定

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. ♣eclipse护眼颜色和关键字颜色设置

    eclipse护眼颜色和字体大小设置   ♣eclipse护眼颜色和关键字颜色设置 ♣eclipse字体大小设置(包括jsp , .xml ,.java) 1.Eclipse字体大小调整: 窗口(Wi ...

  2. UVa 679 - Dropping Balls【二叉树】【思维题】

    题目链接 题目大意: 小球从一棵所有叶子深度相同的二叉树的顶点开始向下落,树开始所有节点都为0.若小球落到节点为0的则往左落,否则向右落.并且小球会改变它经过的节点,0变1,1变0.给定树的深度D和球 ...

  3. 在Adobe Html5 Extension的使用Nodejs的问题

    前情回顾 之前为一个客户开发过一个基于Adobe Premiere的Html5扩展.原本是在Adobe Premiere Pro 2015下面进行调试开发的.一切进展的非常顺利,功能也都正常.但是20 ...

  4. Is there a TRY CATCH command in Bash

    Is there a TRY CATCH command in Bash? No. Bash doesn't have as many luxuries as one can find in many ...

  5. Wan Android 项目总结

    Wan Android 项目总结 项目的由来 这个项目也算是自己学习了一段时间的Android以后的一个总结和学习吧,项目采用了Kotlin语言,Api采用的hongyang大神的WanAndroid ...

  6. JavaScript—异步提交表单的6种方式

    FormData的详细介绍及使用请点击此处,那里对FormData的方法和事件已经表述的非常清楚,这里就不再浪费时间在介绍一遍了.本文主要针对FormData对象的使用以及异步文件上传进行详细的说明. ...

  7. 直接存储器存取(Direct Memory Access,DMA)详细讲解

    一.理论理解部分. 1.直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输. 2.无须CPU干预,数据可以通过DMA快速移动,这就节省了CPU的资源来做其他操作. ...

  8. hihoCoder 1143 : 骨牌覆盖问题·一(递推,矩阵快速幂)

    [题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形 ...

  9. MyBatis初探

    首先下载MyBatis jar包, 可以去MyBatis中文官网下载 项目中导入MyBatis jar包和JDBC jar包(此处用的MySQL) 新建conf.xml 内容如下: <?xml ...

  10. 学习Struts--Chap07:Struts2文件上传和下载

    1.struts2文件上传 1.1.struts2文件上传的基本概述 在开发web应用的时候,我们一般会为用户提供文件上传的功能,比如用户上传一张图像作为头像等.为了能上传文件,我们必须将表单的met ...