Executor框架

来源:互联网 发布:新加坡用什么网络制式 编辑:程序博客网 时间:2024/06/06 09:44
一、概述
   
 Java线程的建与需要一定的开,如果我们为每一个任务创建一个新线程来行,线程的建与将消耗大量的源。同
每一个任务创建一个新线程来行,种策略可能会使于高荷状用最Java线程既是工作元,也是行机制。从JDK 5开始,把工作元与行机制分离开来。工作元包括RunnableCallable,而行机制由Executor框架提供。 

二、框架组成与主要接口

Executor框架主要由3大部分成如下。
  • ·。包括被行任需要实现的接口:Runnable接口或Callable接口。
  • ·行。包括任务执行机制的核心接口Executor,以及承自ExecutorExecutorService接口。Executor框架有两个关键类实现ExecutorService接口ThreadPoolExecutorScheduledThreadPoolExecutor)。
  • ·异步算的果。包括接口Future实现Future接口的FutureTask 

涉及的主要接口和实现


三、线程池工作原理:
阅读ThreadPoolExecutor源码:在该类中维护了两个重要的变量(当然还有其他):
  • private final BlockingQueue<Runnable> workQueue;
  • private final HashSet<Worker> workers new HashSet<Worker>();
结合上面两个属性来分析一下,线程池工作的几种情况,可以参看下面贴的execute()方法源码同步理解。
1.  当前worker数量低于corePoolSize,直接创建新的work执行任务
2. 当前worker数量已达corePoolSize,将任务增加到workQueue;
3. 当前worker数量已达maxSize,且workQueue中不能继续添加任务,则拒绝任务。
4. 线程池中的空闲worker循环从workQueue中获取任务执行,当没有任务可以执行,线程的空闲时间超过keepAliveTime则线程被回收。

execute方法源码:
  1. /**
  2. * Executes the given task sometime in the future. The task
  3. * may execute in a new thread or in an existing pooled thread.
  4. *
  5. * If the task cannot be submitted for execution, either because this
  6. * executor has been shutdown or because its capacity has been reached,
  7. * the task is handled by the current {@code RejectedExecutionHandler}.
  8. *
  9. * @param command the task to execute
  10. * @throws RejectedExecutionException at discretion of
  11. * {@code RejectedExecutionHandler}, if the task
  12. * cannot be accepted for execution
  13. * @throws NullPointerException if {@code command} is null
  14. */
  15. public void execute(Runnable command) {
  16. if (command == null)
  17. throw new NullPointerException();
  18. /*
  19. * Proceed in 3 steps:
  20. *
  21. * 1. If fewer than corePoolSize threads are running, try to
  22. * start a new thread with the given command as its first
  23. * task. The call to addWorker atomically checks runState and
  24. * workerCount, and so prevents false alarms that would add
  25. * threads when it shouldn't, by returning false.
  26. *
  27. * 2. If a task can be successfully queued, then we still need
  28. * to double-check whether we should have added a thread
  29. * (because existing ones died since last checking) or that
  30. * the pool shut down since entry into this method. So we
  31. * recheck state and if necessary roll back the enqueuing if
  32. * stopped, or start a new thread if there are none.
  33. *
  34. * 3. If we cannot queue task, then we try to add a new
  35. * thread. If it fails, we know we are shut down or saturated
  36. * and so reject the task.
  37. */
  38. int c = ctl.get();
  39. if (workerCountOf(c) < corePoolSize) {
  40. if (addWorker(command, true))
  41. return;
  42. c = ctl.get();
  43. }
  44. if (isRunning(c) && workQueue.offer(command)) {
  45. int recheck = ctl.get();
  46. if (! isRunning(recheck) && remove(command))
  47. reject(command);
  48. else if (workerCountOf(recheck) == 0)
  49. addWorker(null, false);
  50. }
  51. else if (!addWorker(command, false))
  52. reject(command);
  53. }

四、各线程池与工作队列的特点:

4.1 各线程池
  1. FixedThreadPool,提供固定数量的线程数的线程池,适用于限制线程数量,服务器负载较重的场景。
  2. SingleThreadExecutor,单线程的线程池,适用于保证任务顺序执行且不会同时有多个活动线程的场景。
  3. CachedThreadPool, corePoolSize=0,根据需要创建线程,线程的数量大小无界,适用于执行很多短期异步或者负载轻的场景。(以上仨继承自ThreadPoolExecutor,以下俩继承自ScheduledThreadPoolExecutor)
  4. ScheduledThreadPoolExecutor,线程数量固定,适用于需要多个后台线程执行周期任务,且后台线程数量需要限制。
  5. SingelThreadScheduledExecutor,单后台线程执行周期任务,适用于保证执行顺序的场景。

4.2 各工作队列
  1. LinkedBlockingQueue, 无界队列(容量为Integer.MAX_VALUE), FixedThreadPool和SingleThreadExecutor采用LinkedBlockingQueue作为workQueue
  2. SynchronousQueue,无容量阻塞队列,每个插入操作必须等待一个线程的移除操作,cachedThreadPool通过使用SynchronousQueue将任务传递给空闲的线程。
  3. DelayedWorkQueue,无界队列,ScheduledThreadPoolExecutor在DelayedWorkQueue获取可以执行的任务。

学习代码
  1. package com.vip.vcp.ryan.zhaunzheng.concurrency.leExecutors;
  2. import java.text.ParseException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.ArrayList;
  5. import java.util.Date;
  6. import java.util.List;
  7. import java.util.concurrent.*;
  8. /**
  9. * 请简要描述Executor框架中提供的线程池的工作原理,并列举各线程池、工作队列类型及其特点。
  10. * Created by ryan01.peng on 2017/6/19.
  11. */
  12. public class LeExecutors {
  13. public static void main(String[] args) {
  14. // testFixedThreadPool();
  15. // testCachedThreadPool();
  16. // testSingleThreadExecutor();
  17. testScheduledThreadPool();
  18. }
  19. private static void testFixedThreadPool(){
  20. ExecutorService executorService1 = java.util.concurrent.Executors.newFixedThreadPool(5);
  21. for (int i = 0; i <10 ; i++) {
  22. executorService1.submit(new RunnableTask(i));
  23. }
  24. }
  25. private static void testSingleThreadExecutor(){
  26. ExecutorService executorService2 = Executors.newSingleThreadExecutor();
  27. for (int i = 0; i <10 ; i++) {
  28. executorService2.submit(new RunnableTask(i));
  29. }
  30. }
  31. private static void testCachedThreadPool(){
  32. ExecutorService executorService3 = Executors.newCachedThreadPool();
  33. List<Future<String>> futureList = new ArrayList<>();
  34. for (int i = 0; i <10 ; i++) {
  35. Future<String> future= executorService3.submit(new CallableTask(i));
  36. futureList.add(future);
  37. }
  38. System.out.println("executorService3线程池循环提交任务结束");
  39. for (Future<String> future : futureList) {
  40. try {
  41. while (!future.isDone());//任务没有返回之前保持等待
  42. System.out.println(future.get());
  43. }catch (InterruptedException e){
  44. e.printStackTrace();
  45. }catch (Exception ex){
  46. ex.printStackTrace();
  47. }finally {
  48. executorService3.shutdown();
  49. }
  50. }
  51. }
  52. private static void testScheduledThreadPool(){
  53. ExecutorService executorService4 = Executors.newScheduledThreadPool(5);
  54. for (int i = 0; i < 10; i++) {
  55. executorService4.submit(new ScheduleTask(i));
  56. }
  57. }
  58. }
  59. /**
  60. * 无返回的可执行任务
  61. */
  62. class RunnableTask implements Runnable{
  63. private int id;
  64. public RunnableTask(int id) {
  65. this.id = id;
  66. }
  67. public RunnableTask() {
  68. }
  69. @Override
  70. public void run() {
  71. System.out.println(Thread.currentThread().getName()+"::RunnableTask -- "+id+" -- 的call方法被调用!!");
  72. }
  73. }
  74. /**
  75. * 有返回的可执行任务
  76. */
  77. class CallableTask implements Callable<String > {
  78. private int id;
  79. public CallableTask(int id) {
  80. this.id = id;
  81. }
  82. public CallableTask() {
  83. }
  84. @Override
  85. public String call() throws Exception {
  86. Thread.sleep(500);
  87. return Thread.currentThread().getName()+"::CallableTask -- "+id+" -- 的call方法被调用!!";
  88. }
  89. }
  90. class ScheduleTask implements Runnable{
  91. private int id;
  92. public ScheduleTask(int id) {
  93. this.id = id;
  94. }
  95. @Override
  96. public void run() {
  97. // if (System.currentTimeMillis()%10 == 0){
  98. System.out.println(Thread.currentThread().getName()+" :: 定时任务"+id+"被调用啦!");
  99. try {
  100. Thread.sleep(2000); //模拟一个任务执行需要两秒
  101. } catch (InterruptedException e) {
  102. e.printStackTrace();
  103. }
  104. System.out.println(Thread.currentThread().getName()+" :: 定时任务"+id+"执行完毕啦!");
  105. // }
  106. }
  107. }


参考资料:
1. http://blog.csdn.net/czw698/article/details/41486245
2. http://www.jiagou4.com/2015/07/726.html
3. Java并发编程的艺术 第十章
4. http://blog.csdn.net/tanxiang21/article/details/17222517
5. http://blog.sina.com.cn/s/blog_9707fac30101i5n5.html

原创粉丝点击