文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。

ExecutorService

Java.util.concurrent.ExecutorService接口代表一种异步执行机制,它能够在后台执行任务。因此ExecutorService与thread pool是非常相似的。事实上,在java.util.package包中ExecutorService的具体实现就是一个线程池的具体实现。

ExcutorService 例子

下面是一个简单的例子

ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();

首先,通过newFixedThreadPool()工厂方法创建一个ExecutorService的实例。这个方法创建了一个可以有10个线程执行任务的线程池。

第二,Runnable接口的匿名实现类作为参数被传递给execute()方法。Runable将会被ExecutorService中的一个线程来执行。

任务委托(Task Delegation)

下面的图片说明了一个线程委托一个任务给ExecutorService进行异步执行:

一旦,线程委托任务给ExecutorService,线程会独立任务的执行而继续自己之后的操作。

ExcutorService的使用说明

下面是委托任务给ExecutorService的一些不同的方式:

  • execute(Runnable)
  • submit(Runnable)
  • submit(Callable)
  • invokeAny(…)
  • invokeAll(…)

下面来逐个看看这些方法。

  • execute(Runnable)

execute(Runnable) 方法接受一个java.lang.Runable对象的实例,并异步执行之。下面是一个使用ExecutorService执行Runnable的例子:

ExecutorService executorService = Executors.newSingleThreadExecutor();executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();

这种方式不能获得Runnable执行的结果,如果有这种需要,你将要使用Callable。

  • submit(Runnable)

submit(Runnable) 方法也接收一个Runnable接口的具体实现,并返回一个Future对象。Future对象可以用来检测Runable是否执行完成。

Future future = executorService.submit(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});future.get();  //returns null if the task has finished correctly.
  • submit(Callable)

submit(Callable)方法与submit(Runnable)方法相似,除了接收的参数有所不同。Callable实例非常类似于Runnable,不同的是call方法可以返回一个结果,Runnable.run()方法不能返回一个结果。

可以通过submit(Callable)方法返回的Future对象获取Callable的结果。下面是一个使用Callable的例子:

Future future = executorService.submit(new Callable(){public Object call() throws Exception {System.out.println("Asynchronous Callable");return "Callable Result";}
});System.out.println("future.get() = " + future.get());

上面代码的输出结果是:

Asynchronous Callable
future.get() = Callable Result
  • invokeAny(…)

invokeAny()方法接收一个Callable对象或者Callable的子接口实例的集合作为参数,这个方法不会返回Future,但会返回集合中某一个Callable的结果。你不能确定你得到是哪个Callable的结果。只是已执行完成的Callable中的一个。

如果一个任务已经完成(或者抛出了异常),剩余的Callable任务将被取消。
下面是示例代码:

ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() {public String call() throws Exception {return "Task 1";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 2";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 3";}
});String result = executorService.invokeAny(callables);System.out.println("result = " + result);executorService.shutdown();

示例代码将会打印给定的Callable集合中一个Callable任务返回的结果。我尝试执行了多次,结果是变化的。有时候是“Task1”,有时候是“Task 2”等。

  • invokeAll(…)

invokeAll()接收一个Callable对象的集合作为参数,该方法会调用你传给他的集合中的所有Callable对象。invokeAll()会返回一个Future对象的列表,通过这个列表你可以获取每一个Callable执行的结果。

记住一个任务可能会因为一个异常而结束,因此这时任务并不是真正意义上执行成功了。这在Future上是没有办法来判断的。

下面是示例代码:

ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() {public String call() throws Exception {return "Task 1";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 2";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 3";}
});List<Future<String>> futures = executorService.invokeAll(callables);for(Future<String> future : futures){System.out.println("future.get = " + future.get());
}executorService.shutdown();

ExecutorService Shutdown

当你是使用完ExecutorService后,你应该关闭它,使得线程不能持续运行。例如,你的应用程序从main()方法开始并且你的主线程退出应用程序,这时如果存在激活状态的ExecutorService,你的应用程序将仍然会保持运行。ExecutorService中激活的线程会阻止JVM关闭。

为了终止ExecutorService中的线程,你需要调用shutdown()方法。ExecutorService不会立即关闭,但是它也不会接受新的任务,直到它里面的所有线程都执行完毕,ExecutorService才会关闭。所有提交到ExecutorService中的任务会在调用shutdown()方法之前被执行。

如果你想立即关闭ExecutorService,你可以调用shutdownNow()方法。这将会尝试立即停止所有正在执行的任务,并且忽略所有提交的但未被处理的任务。对于正在执行的任务是不能确定的,也许它们停止了,也行它们执行直到结束。

ThreadPoolExecutor

Java.util.concurrent.ThreadPoolExecutor类是ExecutorSerivce接口的具体实现。ThreadPoolExecutor使用线程池中的一个线程来执行给定的任务(Runnable或者Runnable)。

ThreadPoolExecutor内部的线程池包含不定数量的线程。池中线程的数量由下面的这些变量决定:

  • corePoolSize
  • maximumPoolSize

当一个任务委托给线程池执行,此时如果池线程中线程数少于corePoolSize,即使池中有空闲的线程,线程池中也会创建一个新的线程。

如果任务队列是满的,corePoolSize个线程或者更多的且少于maximumPoolSize的线程正在运行,也会创建一个新的线程来执行任务。

下面图释ThreadPoolExecutor这种原理:

创建ThreadPoolExecutor

ThreadPoolExecutor有多种构造函数。例如:

int  corePoolSize  =    5;
int  maxPoolSize   =   10;
long keepAliveTime = 5000;ExecutorService threadPoolExecutor =new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

除非你需要显示的给ThreadPoolExecutor指定这些参数,通常使用java.util.concurrent.Executor类中的工厂方法来创建实例。

Java并发包:ExecutorService和ThreadPoolExecutor相关推荐

  1. Java并发包中的几种ExecutorService

    为什么80%的码农都做不了架构师?>>>    1.CachedThreadPool CachedThreadPool首先会按照需要创建足够多的线程来执行任务(Task).随着程序执 ...

  2. 腾讯面试题Java 并发包之线程池综述

    Java 并发包之线程池综述 ■ 线程池的创建 在Java中,您可以通过调整-Xss参数来调节每个线程栈的大小(64bit系统默认1024KB),当减小该值时意味着可以创建更多的线程数,但问题是JVM ...

  3. java 高并发第三阶段实战_Java 高并发第三阶段实战---Java并发包深入解析与使用详解...

    第三阶段的课程主要围绕着Java并发包的使用,展开详细的介绍,主要内容有1.原子包源码剖析,2.并发包工具类详细介绍,3.线程服务以及Future和callable等详细介绍,4.高并发容器和阻塞容器 ...

  4. Java并发包——使用新的方式创建线程

    Java并发包--使用新的方式创建线程 摘要:本文主要学习了如何使用Java并发包中的类创建线程. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520/p/ ...

  5. Java 高并发第三阶段实战---Java并发包深入解析与使用详解

    第三阶段的课程主要围绕着Java并发包的使用,展开详细的介绍,主要内容有1.原子包源码剖析,2.并发包工具类详细介绍,3.线程服务以及Future和callable等详细介绍,4.高并发容器和阻塞容器 ...

  6. java并发包线程池原理分析锁的深度化

    java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...

  7. Java多线程并发编程--Java并发包(JUC)

    Java多线程并发–Java并发包(JUC) 前言 前一篇文章中,笔者已经介绍了Java多线程的一些基础知识,但是想要成为一名中高级Java程序员还必须懂得Java并发包(JUC)的知识点,而且JUC ...

  8. java并发中ExecutorService的使用

    文章目录 创建ExecutorService 为ExecutorService分配Tasks 关闭ExecutorService Future ScheduledExecutorService Exe ...

  9. Java并发包--线程池框架

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509903.html 线程池架构图 线程池的架构图如下: 1. Executor 它是"执行者 ...

最新文章

  1. setup.py安装
  2. box-sizing 属性
  3. centos mysql卸载重装_提高性能,MySQL 读写分离环境搭建
  4. java恶意小程序_小程序java实现校验一张图片是否含有违法违规内容security.imgSecCheck...
  5. linux fedora安装flameshot火焰截图
  6. python和javascript哪个好_JavaScript与Python:主要区别
  7. php底层实现也是c语言,深入php内核,从底层c语言剖析php实现原理
  8. 2017程序员综合素质调研测试
  9. 2021桂花开得真晚,晚了将近一个月
  10. 富士施乐Fuji Xerox DocuPrint CP215 w 驱动
  11. 发出商品杀手锏之SAP在途库存解决方案
  12. 仙侣情缘之麒麟劫java_《仙侣情缘之麒麟劫》详细流程攻略[多图]
  13. 用Java写数据结构作业——7-1 拯救007
  14. 你真的了解前端模块化吗?
  15. 一个点击率10万+的恶搞程序送给大家!
  16. 迪赛智慧数——饼图(玫瑰饼图):世界厨师日之-从业时间
  17. “双减”政策下的少儿编程市场:前8月融资12起,资本加持下何时跑出“独角兽”?...
  18. 2018最受欢迎开源免费CMS建站系统排行榜
  19. 音乐的格式、选择和音质说明
  20. js知道年月日怎么获取到是周几,和几月几号

热门文章

  1. 浅谈 Fhq-Treap
  2. java jtextarea边框_JTextArea在java swing中的边框
  3. Putty登陆root输入密码被拒绝(没开启ssh)
  4. npm引入gojs如何去除水印
  5. 网站建设需要网站服务器吗
  6. Servlet - Sessions and Cookies
  7. 【Matlab】input 请求用户输入
  8. Shiro(一)之shiro简介与工作原理
  9. Python(1)自动发送邮件
  10. Windows RPC 初体验