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. Rendering React components to the document body

    React一个比较好用的功能是其简单的API,一个组件可以简单到一个return了组件结构的render函数.除了一个简单的函数之外,我们还有了一段有用且可复用的代码片段. 问题 不过有时候可能会受到 ...

  2. P2347 砝码称重-DP方案数-bitset

    P2347 砝码称重 DP做法 : 转化为 01背包. 进行方案数 更新.最后统计种类. #include<bits/stdc++.h> using namespace std; #def ...

  3. XamarinSQLite教程Xamarin.Android项目添加引用

    XamarinSQLite教程Xamarin.Android项目添加引用 在Xamarin.Android项目中,导入System.Data和Mono.Data.SQLite库的操作步骤如下: (1) ...

  4. BZOJ3877 : [Ahoi2014&Jsoi2014]保龄球

    考虑从前往后放所有轮. 如果上一轮是全中: 那么这一轮如果是补中,一定放第一次最小的,这样可以让第一次大的放在其它补中之后. 如果这一轮是失误,那么一定放总分最大的. 如果上一轮是补中: 这一轮一定放 ...

  5. BZOJ4083 : [Wf2014]Wire Crossing

    WF2014完结撒花~ 首先求出所有线段之间的交点,并在交点之间连边,得到一个平面图. 这个平面图不一定连通,故首先添加辅助线使其连通. 然后求出所有域,在相邻域之间连一条代价为$1$的边. 对起点和 ...

  6. HTML(三)

    html图像.绝对路径和相对路径 html图像 <img>标签可以在网页上插入一张图片,它是独立使用的标签,通过“src”属性定义图片的地址,通过“alt”属性定义图片加载失败时显示的文字 ...

  7. 志愿者招募 [NOI2008] [鬼畜网络流]

    Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完 ...

  8. sql需注意事项

    sql语句中String类型数据一定需要加引号,浏览器的访问一定不能加引号,

  9. yii创建控制台命令

    创建控制台命令程序1.控制台命令继承自 yii\console\Controller控制器类2.在控制器类中,定义一个或多个动作,动作与控制台子命令相对应3.在动作方法中实现业务需求的代码 运行控制台 ...

  10. HTTP断点续传

    一.概述   所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载.在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了.一般断点下载时才用到Range和Conten ...