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…

Java代码格式化算法_一个时间格式化的工具类:TimeUtil

源代码如下&#xff1a;import android.content.Context;import android.text.TextUtils;import android.text.format.DateUtils;import java.text.Format;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.regex.Matcher…

(转)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;表单元素比非表单元素的优…

18. 使用模板【从零开始学Spring Boot】

转&#xff1a;http://blog.csdn.net/linxingliang/article/details/52017098 18.1 使用thymeleaf 整体步骤&#xff1a; &#xff08;1&#xff09; 在pom.xml中引入thymeleaf; &#xff08;2&#xff09; 如何关闭thymeleaf缓存 &#xff08;3&#xff09; …

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

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

Hadoop + Amazon EC2 –更新的教程

在Hadoop的Wiki页面上放置了一个旧教程&#xff1a; http : //wiki.apache.org/hadoop/AmazonEC2 &#xff0c;但是最近我不得不遵循本教程&#xff0c;并且我注意到它没有涵盖某些Amazon新功能。 建议您已经熟悉Hadoop的基础来遵循本教程&#xff0c;可以在Hadoop的主页http:…

oracle11g 修改字符集 修改为ZHS16GBK

转&#xff1a;http://www.cnblogs.com/jay-xu33/p/5210098.html oracle11g 修改字符集 修改为ZHS16GBK1.cmd下,cd到oracle数据库软件的服务器端 如&#xff1a;D:\app\Administrator\product\11.2.0\dbhome_1\BIN 2.输入set ORACLE_SID你想进入的数据库的那个sid 3.输入 sqlpl…

浏览器内核

浏览器的四大内核&#xff1a; Trident&#xff0c;Gecko&#xff0c;Webkit&#xff0c;Blink。 不同的内核对网页编写语法的解释也有不同&#xff0c;进而导致同一个页面在不同内核的浏览器下显示出来的效果也会有所出入&#xff0c;这也是作为一个前端工程师需要了解不同浏…

2017.4.14 Java String.split()用法小结

在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1、如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split("."); 2、如果用“|”作为分隔的话,必…

java线程统一_Java线程结果不一致

我有一个实现可运行的线程类和一个int计数器作为实例变量。两种同步方法add和sub。当我以某种方式运行测试类时&#xff0c;它几次会输出错误的结果。据我了解&#xff0c;当方法同步时&#xff0c;整个对象将被锁定以供其他线程访问&#xff0c;这种逻辑每次我们都应该获得相同…

markdown-Macdown

#标题 [页面锚点](#name) > <a name"name"></a>文字 **加粗**(Command-B) *斜体*(Command-I) * * * 或者 - -- 无序列表 1. 2. 3. 有序列表 、、、 代码段 、、、 或者用 ~ 代替 或者 上下空一行每行缩进4个空格 <http://www.baidu.com>链…

什么是web标准??

web标准 不是某一个标准&#xff0c;而是一系列标准的集合。网页主要由三部分组成&#xff1a;结构&#xff08;Structure&#xff09;、表现&#xff08;Presentation&#xff09;和行为&#xff08;Behavior&#xff09;。对应的标准也分三方面&#xff1a;结构化标准语言主…

有没有更好的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;主页面局部刷新用户信息。本文我们将给大家介绍如何使…

【CPU】解决打开360或者Chrome浏览器CPU占用过高

cmd 运行&#xff1a; RD /s /q "%USERPROFILE%\AppData\Roaming\Microsoft\Protect"转载于:https://www.cnblogs.com/zwqh/p/6708398.html

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

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

css盒模型中margin很牛逼

css盒子模型&#xff0c;说简单也简单&#xff0c;用的时候也有不简单的。 其中margin的值可以为负值&#xff0c;并且为了实现margin&#xff0c;忽略父级的padding、border、甚至定位。这在布局上很有用&#xff0c;要注意。 ------------ 比如&#xff0c;div1&#xff0…

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

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