Java并发执行器的懒惰开发人员简介

如果我告诉您util.concurrent API自2004年起提供此类服务,我就会自欺欺人。但是,我想回顾一下一些很酷的功能。 并发专家,现在是时候关闭该窗口了。 所有其他人,请紧紧抓住乐趣。

你不会忘记你的根源

执行程序是具有单个执行方法的根接口。 任何实现Runnable接口的东西都可以作为参数传递。 但是,傻傻的执行器不支持Callable。

好消息: ExecutorService接口扩展了Executor,增加了对Callable的支持。 它的实现类是ThreadPoolExecutor。

我要假装ScheduledExecutorService接口及其实现类ScheduledThreadPoolExecutor不存在,因为它们只是在ExecutorService和ThreadPoolExecutor之上添加了调度功能。 但是,当功能强大但无聊的java.util.Timer不够用,而功能强大的外部调度程序实在太多了时,请记住此类。

如果您不熟悉并发性,或者忘记了Callable和Runnable之间的区别,则可能需要先阅读一点,然后再继续阅读。 虚拟指南在这里

ExecutorService.submit事实:

这三个提交变量:

将来提交(可调用任务)
将来提交(可运行任务)
将来提交(可运行任务,T结果)

  1. 所述submit的的ExecutorService的方法过载并且可以接受一个CallableRunnable
  2. 由于Runnable的run方法返回void,因此在任务完成时Future.get总是返回null也就Future.get了。
    Future<?>   submit(Runnable task)
  3. 另一个接受Runnable和泛型的重载submit方法将返回您作为第二个参数传入的结果。
    <T> Future<T>   submit(Runnable task, T result)

事实上,开放代码( FutureTask ),你会发现, RunnableAdapter顶级嵌套类的Executors只需保存结果,并返回相同的结果run方法完成之后。

static final class RunnableAdapter<T> implements Callable<T> {final Runnable task;final T result;RunnableAdapter(Runnable task, T result) {this.task = task;this.result = result;}public T  [More ...] call() {task.run();return result;}
}

RunnableAdapter源

在这两种情况下,如果您想要(应该!)终止程序,而不是执行程序线程阻止该程序并进入繁忙循环 ,则应按以下方式调用shutdown方法:

executorService.shutdown()

关闭事实

您可以想象shutdown是购物中心的半关门。 不会有新客户进入,但现有客户一旦完成就可以离开购物中心。

重申一下,

  1. shutdown是一种礼貌的方法。 它实际上并不会立即关闭池中的任务。 它只是说不会接受任何新任务。
  2. 除非您使用invokeAll执行任务,否则需要等待所有正在进行的任务完成。 这可以通过调用awaitTermination方法来实现。 (invokeAll并在帖子底部提交示例)
  3. 当前所有任务完成后,执行程序服务将关闭。

如果您需要一种不礼貌的侵入方法,而该方法不关心当前线程是否已完成其任务,那么shutdownNow是您的理想选择。 但是,不能保证该方法将关闭点上的服务,但这是您必须立即关闭的最接近的方法。

在awaitTermination上,您可以指定超时时间,直到主线程等待池线程完成其任务为止。

ExecutorService executorService=Executors.newFixedThreadPool(10);…future = executorService.submit(getInstanceOfCallable(count,sum));…executorService.shutdown();if (executorService.awaitTermination(10, TimeUnit.SECONDS)){System.out.println('All threads done with their jobs');}

执行者–工厂的家伙

上面的课程都很棒。 但是,例如,您想创建一个单线程执行器,您将编写类似

new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

比较一下

Executors.newSingleThreadExecutor()

所以,你去。 Executors是仅具有工厂方法的类,用于使用各种常用默认值创建各种形式的executor服务。 请注意,除了很棒的工厂方法外,它没有为表带来任何新功能。

建议您快速查看工厂方法的实现,并检查它是否适合您的需求。

invokeAll和提交

ExecutorServiceinvokeAll方法的All部分毫不奇怪。 它只是说您需要传递Callable的Collection。 再次,正如预期的那样,该方法直到所有线程完成其任务后才返回。 因此,对于仅在所有工作完成后才对结果感兴趣的情况, invokeAll是您的最佳选择。

另一方面, submit方法在可调用对象被提交给执行者服务之后立即返回。 除非您在Callable call方法中什么都不做,否则理想情况下,当submit方法返回时,工作线程应该正在运行。

以下示例可能对您有用。 这些程序只是尝试找到所有自然数的和,直到100(当然是蛮力)

package me.rerun.incubator;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;public class ExecutorInvokeAll {public void runApp() throws InterruptedException, ExecutionException{//variable to store the sumAtomicInteger sum=new AtomicInteger();//Use our friendly neighbourhood factory method of the Executors.ExecutorService executorService=Executors.newFixedThreadPool(10);List<Callable<AtomicInteger>> callableList=new ArrayList<Callable<AtomicInteger>>();for (int count = 0; count <= 100;count++) {callableList.add(getInstanceOfCallable(count,sum));}//returns only after all tasks are completeList<Future<AtomicInteger>> resultFuture = executorService.invokeAll(callableList);//Prints 5050 all throughfor (Future<AtomicInteger> future : resultFuture) {//Didn't deliberately put a timeout here for the get method. Remember, the invoke All does not return until the task is done.System.out.println("Status of future : " + future.isDone() +". Result of future : "+future.get().get());}executorService.shutdown();// You might as well call a resultFuture.get(0).get().get() and that would give you the same //result since all your worker threads hold reference to the same atomicinteger sum.System.out.println("Final Sum : "+sum); }//Adds count to the sum and returns the reference of the sum as the resultprivate Callable<AtomicInteger> getInstanceOfCallable(final int count, final AtomicInteger sum) {Callable<AtomicInteger> clientPlanCall=new Callable<AtomicInteger>(){public AtomicInteger call() {sum.addAndGet(count);System.out.println("Intermediate sum :"+sum);return sum;}};return clientPlanCall;}public static void main(String[] args) throws ExecutionException {try {new ExecutorInvokeAll().runApp();} catch (InterruptedException e) {e.printStackTrace();}} }
package me.rerun.incubator;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;public class ExecutorSubmit {public void runApp() throws InterruptedException, ExecutionException{//holder for the total sumAtomicInteger sum=new AtomicInteger();//Use the factory method of ExecutorsExecutorService executorService=Executors.newFixedThreadPool(10);Future<AtomicInteger> future = null;for (int count = 0; count <= 100; count++) {future = executorService.submit(getInstanceOfCallable(count,sum));//prints intermediate sumtry {System.out.println("Status of future : " + future.isDone() +". Result of future : "+future.get(1000, TimeUnit.MILLISECONDS).get());} catch (TimeoutException e) {System.out.println("<IGNORE> Timeout exception for count : "+count);//e.printStackTrace();}//System.out.println("Result of future : "+future.get().get() +".Status of future : " + future.isDone());}executorService.shutdown();if (executorService.awaitTermination(10, TimeUnit.SECONDS)){System.out.println("All threads done with their jobs");}//execSystem.out.println("Final Sum : "+sum);}//Adds count to the sum and returns the reference of the sum as the resultprivate Callable<AtomicInteger> getInstanceOfCallable(final int count, final AtomicInteger sum) {Callable<AtomicInteger> clientPlanCall=new Callable<AtomicInteger>(){public AtomicInteger call() {sum.addAndGet(count);//System.out.println("Intermediate sum :"+sum);return sum;}};return clientPlanCall;}public static void main(String[] args) throws ExecutionException {try {new ExecutorSubmit().runApp();} catch (InterruptedException e) {e.printStackTrace();}} }

进一步阅读:

亚历克斯·米勒的惊人博客

亚历克斯·米勒的并发陷阱

Vogella关于与原始API进行比较的文章

总体上很好地介绍了并发

强烈推荐有关Java并发性的书

祝您编程愉快,别忘了分享!

参考: Rerun.me博客上的JCG合作伙伴 Arun Manivannan的Java并发执行器懒惰开发人员简介 。


翻译自: https://www.javacodegeeks.com/2012/10/a-lazy-developers-introduction-to-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《我们应该怎样做需求分析》阅读笔记

认识&#xff1a;软件需求分析是贯穿软件项目从出生到成长或者死亡的&#xff0c;我们必须搞清楚到手的软件是为了什么要做什么做成什么样&#xff0c;通过顾客的描述彼此的合作分析需求与业务逻辑&#xff0c;不断改进从而实现软件在合理范围内符合顾客要求。 怎么做&#xff…

(转)VS2010/MFC编程入门之前言

鸡啄米的C编程入门系列给大家讲了C的编程入门知识&#xff0c;大家对C语言在语法和设计思想上应该有了一定的了解了。但是教程中讲的例子只是一个个简单的例程&#xff0c;并没有可视化窗口。鸡啄米在这套VS2010/MFC编程入门教程中将会给大家讲解怎样使用VS2010进行可视化编程&…

JavaOne 2012:JavaFX图形技巧和窍门

我回到希尔顿&#xff08;皇家宴会厅B&#xff09;看了Richard Bair的&#xff08;Oracle Java客户架构师&#xff09;的“ JavaFX图形技巧和窍门”。 Bair与FX Experience相关联&#xff0c;并且显然了解JavaFX。 拜尔说&#xff0c;他演讲的主题是表演。 他告诫说&#xff0c…

web前端知识点1

1. input属于窗体元素,层级显示比flash、其它元素都高。请判断这句话的正确与否。 错误 层级显示优先级&#xff1a; frameset > 表单元素 > 非表单元素 在html中&#xff0c;帧元素&#xff08;frameset&#xff09;的优先级最高&#xff0c;表单元素比非表单元素的优…

java单元测试算初级_Java____Eclipse下JUnit单元测试(初级)

给大家分享一个链接希望对你们有帮助 http://blog.csdn.net/huangbiao86/article/details/6709742今天看图片命名唯一的策略时看到有个大大用JUnit测试&#xff0c;神奇的样子&#xff0c;遂上网搜集来三篇JUnit测试的入门文章&#xff0c;作为参考。原作地址在上面&#xff0c…

有没有更好的Marker方法?

自Java 1.5推出以来&#xff0c;就是否在Java中使用Marker接口进行了广泛的讨论和辩论。 这是因为Java 1.5引入了注释功能&#xff0c;这些功能几乎可以解决Marker接口的目的。 本文将涵盖这场辩论的一个有趣的部分。 定义&#xff1a; Java中的标记接口是一个空接口&#xff…

php jquery ajax登录,jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)

弹出层主要用于展示丰富的页面信息&#xff0c;还有一个更好的应用是弹出表单层丰富交互应用。常见的应用有弹出登录表单层&#xff0c;用户提交登录信息&#xff0c;后台验证登录成功后&#xff0c;弹出层消失&#xff0c;主页面局部刷新用户信息。本文我们将给大家介绍如何使…

# 20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践+myod

20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践myod 因为在课上已经提交了四个实验&#xff0c;还欠缺最后一个实验&#xff0c;反省一下自己还是操作不熟练&#xff0c;平时在课下应该多多练习linux的命令训练。 实践一 每个* .c一个文件&#xff0c;每个*.h一…

CometD:Java Web应用程序的Facebook类似聊天

聊天就像吃一块蛋糕或喝一杯热咖啡一样容易。 您是否曾经考虑过自己开发聊天程序&#xff1f; 您知道&#xff0c;聊天不容易。 但是&#xff0c;如果您是开发人员&#xff0c;并且阅读了本文的结尾&#xff0c;则可以尝试自己开发一个聊天应用程序&#xff0c;并允许您的用户通…

怎么用PHP建立购物网站,如何使用PHP建设一个购物网站

本系统以PHP为主要制作工具&#xff0c;实现了用户注册、登录、验证身份及用户数据的采集、物品的预览查询、搜索/查看物品信息&#xff0c;站内最新物品信息发布&#xff0c;可进入在线下单从而实现了网络销售。网上购物&#xff0c;这个逐渐流行于二十世纪的购物方式已经为越…

团队作业2——需求分析原型设计

需求分析&#xff1a; 软件的最终目的是用来解决用户的某些问题&#xff0c;需求分析就是要理解要解决的问题&#xff0c;真正明确用户需求。请发表一篇随笔&#xff0c;完成初步的需求分析&#xff1a; 1.访问软件项目的真实用户&#xff08;至少10个&#xff09;&#xff0c;…

给div命名,使逻辑更加清晰

我们把一些标签放进<div>里&#xff0c;划分出一个独立的逻辑部分。为了使逻辑更加清晰&#xff0c;我们可以为这一个独立的逻辑部分设置一个名称&#xff0c;用id属性来为<div>提供唯一的名称&#xff0c;这个就像我们每个人都有一个身份证号&#xff0c;这个身份…

css边框颜色渐变

在实际开发中&#xff0c;我们经常遇见边框需要背景渐变的实现要求&#xff0c;那么如何去实现呢&#xff0c;今天给大家分享依稀几种情况 1.直角的背景渐变 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta…

170406、用uid分库,uname(用户名)上的查询怎么办

【缘起】 用户中心是几乎每一个公司必备的基础服务&#xff0c;用户注册、登录、信息查询与修改都离不开用户中心。 当数据量越来越大时&#xff0c;需要多用户中心进行水平切分。最常见的水平切分方式&#xff0c;按照uid取模分库&#xff1a; 通过uid取模&#xff0c;将数据分…

bzoj2144: 跳跳棋(二分/倍增)

思维好题&#xff01; 可以发现如果中间的点要跳到两边有两种情况&#xff0c;两边的点要跳到中间最多只有一种情况。 我们用一个节点表示一种状态&#xff0c;那么两边跳到中间的状态就是当前点的父亲&#xff0c;中间的点跳到两边的状态就是这个点的两个儿子&#xff0c;从而…

电脑投屏软件哪个好_目前当贝市场中投屏软件哪个好,最全面投屏技巧盘点

现在不管是在家里还是公司里&#xff0c;为了看一些是视频和资料&#xff0c;投屏到电视上是一件非常必要的事情&#xff0c;但是现在投屏的技巧各种各样&#xff0c;投屏的软件也是五花八门&#xff0c;小编平常也是经常投屏&#xff0c;也试过非常多的方法&#xff0c;这边分…

从零开始的全栈工程师——html篇1.2

起名方式与CSS 一.起名方式(起名方式也叫选择器) 起名的目的是为了给标签添加属性 常见的3种选择器有 标签选择器 id选择器(使用的时候加#) class选择器(使用的时候加.) 样式的要求是由选择器的权重来决定的 标签的权重为1 class的权重是10 id的权重是100 权重是可…

Spring:设置日志依赖项

这篇文章描述了如何在Spring中设置日志依赖。 它基于Dave Syer的帖子中提供的信息 。 这里提供有关Java日志记录框架的提醒。 该代码示例可在GitHub的Spring-Logging-Dependencies目录中找到。 Spring使用Jakarta Commons Logging API&#xff08;JCL&#xff09;。 不幸的是&…

安卓app开发工具_怎么开发app软件需要多少钱?主流app开发工具盘点

现在智能手机的快速普及让手机app在生活中越来越重要&#xff0c;很多企业及创业者也意识到了app的重要性&#xff0c;但是怎么开发app软件&#xff1f;有哪些主流app开发工具呢&#xff1f;这里就为大家分享一下如何快速开发app软件。一、编程app开发工具主要针对专业的程序员…

大话设计模式读书笔记(十一) 观察者模式

观察者模式&#xff1a; 书中通过小菜描述同事在公司看股票行情&#xff0c;并请求前台帮忙在老板回来时提醒同事&#xff0c;引出需求。将前台通知同事老板回来的事写成程序。未用模式实现&#xff1a; 1 //前台类2 public class Secretary {3 private List<StockObser…