文档章节

ThreadPoolExecutor执行过程分析

4rnold
 4rnold
发布于 06/23 23:47
字数 2237
阅读 17
收藏 1

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize:线程池核心线程数(平时保留的线程数)
  • maximumPoolSize:线程池最大线程数(当workQueue都放不下时,启动新线程,最大线程数)
  • keepAliveTime:超出corePoolSize数量的线程的保留时间。
  • unit:keepAliveTime单位
  • workQueue:阻塞队列,存放来不及执行的线程
    • ArrayBlockingQueue:构造函数一定要传大小
    • LinkedBlockingQueue:构造函数不传大小会默认为65536(Integer.MAX_VALUE ),当大量请求任务时,容易造成 内存耗尽。
    • SynchronousQueue:同步队列,一个没有存储空间的阻塞队列 ,将任务同步交付给工作线程。
    • PriorityBlockingQueue : 优先队列
  • threadFactory:线程工厂
  • handler:饱和策略
    • AbortPolicy(默认):直接抛弃
    • CallerRunsPolicy:用调用者的线程执行任务
    • DiscardOldestPolicy:抛弃队列中最久的任务
    • DiscardPolicy:抛弃当前任务

ThreadPoolExecutor 测试代码

//test.java
volatile int finishState = 0;


@Test
public void test4() throws InterruptedException, ExecutionException {
   ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 7, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10));
   ExecutorCompletionService<String> executorCompletionService = new ExecutorCompletionService(threadPoolExecutor);

   Runnable runnable = new Runnable() {
      @Override
      public void run() {
         for (int i = 0; i < 50; i++) {
            String name = "name_" + i;
            TestCallable testCallable = new TestCallable(name);
            try {
               executorCompletionService.submit(testCallable);

               synchronized (lock) {
                  System.out.print("+++添加任务 name: " + name);
                  System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
                  System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
                  System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
                  System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());
               }
            } catch (RejectedExecutionException e) {
               synchronized (lock) {
                  System.out.println("拒绝:" + name);
               }
            }
            try {
               Thread.sleep(200);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
         finishState = 1;
      }
   };

   Thread addThread = new Thread(runnable);
   addThread.start();

   //System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());

   //添加的任务有被抛弃的。taskCount不一定等于添加的任务。
   int completeCount = 0;
   while (!(completeCount == threadPoolExecutor.getTaskCount() && finishState == 1)) {
      Future<String> take = executorCompletionService.take();
      String taskName = take.get();
      synchronized (lock) {
         System.out.print("---完成任务 name: " + taskName);
         System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
         System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
         System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
         System.out.print(" taskCount: " + threadPoolExecutor.getTaskCount());
         System.out.println(" finishTask:" + (++completeCount));

      }
   }

   addThread.join();


   while (threadPoolExecutor.getPoolSize() > 0) {
      Thread.sleep(1000);
      synchronized (lock) {
         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
         System.out.print(simpleDateFormat.format(new Date()));
         //System.out.print("name: " + taskName);
         System.out.print(" ActiveCount: " + threadPoolExecutor.getActiveCount());
         System.out.print(" poolSize: " + threadPoolExecutor.getPoolSize());
         System.out.print(" queueSize: " + threadPoolExecutor.getQueue().size());
         System.out.println(" taskCount: " + threadPoolExecutor.getTaskCount());
      }
   }

   // Tell threads to finish off.
   threadPoolExecutor.shutdown();
   // Wait for everything to finish.
   while (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
      System.out.println("complete");
   }

}
//TestCallable.java
public class TestCallable implements Callable<String>{


   private String name;

   public TestCallable(String name) {
      this.name = name;
   }

   @Override
   public String call() throws Exception {
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      return this.name;
   }
}

执行结果

+++添加任务 name: name_0 ActiveCount: 1 poolSize: 1 queueSize: 0 taskCount: 1
+++添加任务 name: name_1 ActiveCount: 2 poolSize: 2 queueSize: 0 taskCount: 2
+++添加任务 name: name_2 ActiveCount: 3 poolSize: 3 queueSize: 0 taskCount: 3
//corePoolSize=3,所以poolSize逐渐加到3.
+++添加任务 name: name_3 ActiveCount: 3 poolSize: 3 queueSize: 1 taskCount: 4
+++添加任务 name: name_4 ActiveCount: 3 poolSize: 3 queueSize: 2 taskCount: 5
+++添加任务 name: name_5 ActiveCount: 3 poolSize: 3 queueSize: 3 taskCount: 6
+++添加任务 name: name_6 ActiveCount: 3 poolSize: 3 queueSize: 4 taskCount: 7
+++添加任务 name: name_7 ActiveCount: 3 poolSize: 3 queueSize: 5 taskCount: 8
+++添加任务 name: name_8 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 9
+++添加任务 name: name_9 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 10
---完成任务 name: name_0 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 10 finishTask:1
+++添加任务 name: name_10 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 11
---完成任务 name: name_1 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 11 finishTask:2
+++添加任务 name: name_11 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 12
---完成任务 name: name_2 ActiveCount: 3 poolSize: 3 queueSize: 6 taskCount: 12 finishTask:3
+++添加任务 name: name_12 ActiveCount: 3 poolSize: 3 queueSize: 7 taskCount: 13
+++添加任务 name: name_13 ActiveCount: 3 poolSize: 3 queueSize: 8 taskCount: 14
+++添加任务 name: name_14 ActiveCount: 3 poolSize: 3 queueSize: 9 taskCount: 15
+++添加任务 name: name_15 ActiveCount: 3 poolSize: 3 queueSize: 10 taskCount: 16
//因为任务队列为:new LinkedBlockingDeque<>(10),core线程不够用时,将任务添加到队列中。
//queueSize到10,队列已满。开始增加poolSize,加到maximumPoolSize=7
+++添加任务 name: name_16 ActiveCount: 4 poolSize: 4 queueSize: 10 taskCount: 17
+++添加任务 name: name_17 ActiveCount: 5 poolSize: 5 queueSize: 10 taskCount: 18
+++添加任务 name: name_18 ActiveCount: 6 poolSize: 6 queueSize: 10 taskCount: 19
+++添加任务 name: name_19 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 20
---完成任务 name: name_3 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 20 finishTask:4
+++添加任务 name: name_20 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 21
---完成任务 name: name_4 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 21 finishTask:5
+++添加任务 name: name_21 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 22
---完成任务 name: name_5 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 22 finishTask:6
+++添加任务 name: name_22 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 23
//poolSize=maximumPoolSize,queueSize=10,都满了。执行饱和策略。默认AbortPolicy抛弃新任务。
拒绝:name_23
拒绝:name_24
拒绝:name_25
---完成任务 name: name_16 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 23 finishTask:7
+++添加任务 name: name_26 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 24
---完成任务 name: name_17 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 24 finishTask:8
+++添加任务 name: name_27 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 25
---完成任务 name: name_18 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 25 finishTask:9
+++添加任务 name: name_28 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 26
---完成任务 name: name_19 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 26 finishTask:10
+++添加任务 name: name_29 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 27
---完成任务 name: name_6 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 27 finishTask:11
+++添加任务 name: name_30 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 28
---完成任务 name: name_7 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 28 finishTask:12
+++添加任务 name: name_31 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 29
---完成任务 name: name_8 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 29 finishTask:13
+++添加任务 name: name_32 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 30
拒绝:name_33
拒绝:name_34
拒绝:name_35
---完成任务 name: name_9 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 30 finishTask:14
+++添加任务 name: name_36 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 31
---完成任务 name: name_10 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 31 finishTask:15
+++添加任务 name: name_37 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 32
---完成任务 name: name_11 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 32 finishTask:16
+++添加任务 name: name_38 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 33
---完成任务 name: name_12 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 33 finishTask:17
+++添加任务 name: name_39 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 34
---完成任务 name: name_13 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 34 finishTask:18
+++添加任务 name: name_40 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 35
---完成任务 name: name_14 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 35 finishTask:19
+++添加任务 name: name_41 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 36
---完成任务 name: name_15 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 36 finishTask:20
+++添加任务 name: name_42 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 37
拒绝:name_43
拒绝:name_44
拒绝:name_45
---完成任务 name: name_20 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 37 finishTask:21
+++添加任务 name: name_46 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 38
---完成任务 name: name_21 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 38 finishTask:22
+++添加任务 name: name_47 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 39
---完成任务 name: name_22 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 39 finishTask:23
//消费速度大于添加速度,poolSize并不减少,先把queue中的任务逐一执行完成。
+++添加任务 name: name_48 ActiveCount: 7 poolSize: 7 queueSize: 10 taskCount: 40
---完成任务 name: name_26 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 40 finishTask:24
---完成任务 name: name_27 ActiveCount: 7 poolSize: 7 queueSize: 8 taskCount: 40 finishTask:25
+++添加任务 name: name_49 ActiveCount: 7 poolSize: 7 queueSize: 9 taskCount: 41
---完成任务 name: name_28 ActiveCount: 7 poolSize: 7 queueSize: 8 taskCount: 41 finishTask:26
---完成任务 name: name_29 ActiveCount: 7 poolSize: 7 queueSize: 7 taskCount: 41 finishTask:27
---完成任务 name: name_30 ActiveCount: 7 poolSize: 7 queueSize: 6 taskCount: 41 finishTask:28
---完成任务 name: name_31 ActiveCount: 7 poolSize: 7 queueSize: 5 taskCount: 41 finishTask:29
---完成任务 name: name_32 ActiveCount: 7 poolSize: 7 queueSize: 4 taskCount: 41 finishTask:30
---完成任务 name: name_36 ActiveCount: 7 poolSize: 7 queueSize: 3 taskCount: 41 finishTask:31
---完成任务 name: name_37 ActiveCount: 7 poolSize: 7 queueSize: 2 taskCount: 41 finishTask:32
---完成任务 name: name_38 ActiveCount: 7 poolSize: 7 queueSize: 1 taskCount: 41 finishTask:33
---完成任务 name: name_39 ActiveCount: 7 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:34
//ActiveCount开始减少。
---完成任务 name: name_40 ActiveCount: 6 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:35
---完成任务 name: name_41 ActiveCount: 5 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:36
---完成任务 name: name_42 ActiveCount: 4 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:37
---完成任务 name: name_46 ActiveCount: 3 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:38
---完成任务 name: name_47 ActiveCount: 2 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:39
---完成任务 name: name_48 ActiveCount: 1 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:40
---完成任务 name: name_49 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41 finishTask:41
22:47:49 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:50 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:51 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:52 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:53 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:54 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:55 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:56 ActiveCount: 0 poolSize: 7 queueSize: 0 taskCount: 41
22:47:57 ActiveCount: 0 poolSize: 5 queueSize: 0 taskCount: 41
//由于keepAliveTime=10,大概10s后poolSize恢复为corePoolSize。
22:47:58 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41
22:47:59 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41
22:48:00 ActiveCount: 0 poolSize: 3 queueSize: 0 taskCount: 41

注意

《阿里巴巴java开发手册》

线程池不使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明: Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。
  2. CachedThreadPool 和 ScheduledThreadPool : 允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。

Reference

© 著作权归作者所有

共有 人打赏支持
4rnold
粉丝 1
博文 51
码字总数 26866
作品 0
深圳
程序员
私信 提问
Java 线程池框架核心代码分析

原文出处:肖汉松 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的。线程池应运而生,成为我们管理线程的利器。Java 通过Executor接口,提供了一...

肖汉松
2017/12/17
0
0
JDK线程池源码分析之ThreadPoolExecutor

前言 JDK中为我们提供了一个并发线程框架,它是的我们可以在有异步任务或大量并发任务需要执行时可以使用它提供的线程池,大大方便了我们使用线程,同时将我们从创建、管理线程的繁琐任务中解...

Justlearn
2017/04/24
0
0
ThreadPoolExecutor源码详解

我之前一篇文章谈到了ThreadPoolExecutor的作用(http://my.oschina.net/xionghui/blog/494004),这篇文章介绍下它的原理,并根据原理分析下它的实现源码。 我们先来查看一下ThreadPoolExe...

xionghuiCoder
2015/08/19
0
3
Java调度线程池ScheduledThreadPoolExecutor源码分析

最近新接手的项目里大量使用了ScheduledThreadPoolExecutor类去执行一些定时任务,之前一直没有机会研究这个类的源码,这次趁着机会好好研读一下。 该类主要还是基于ThreadPoolExecutor类进行...

凌风郎少
2017/10/22
0
0
JAVA线程池shutdown和shutdownNow的区别

shutDown() 当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出...

Zero零_度
2015/12/18
24
0

没有更多内容

加载失败,请刷新页面

加载更多

window下安装maven

1.下载软件包: 2.解压到当前的安装路径: D:\Maven3.5.3 3.添加环境变量: 新建一个名为:MAVEN_HOME 填写解压路径:D:\Maven3.5.3 打开path,添加:%MAVEN_HOME%\bin 确定即可。 4.验证环境...

狼王黄师傅
8分钟前
0
0
聊聊flink的FsCheckpointStorage

序 本文主要研究一下flink的FsCheckpointStorage CheckpointStorage flink-runtime_2.11-1.7.0-sources.jar!/org/apache/flink/runtime/state/CheckpointStorage.java /** * CheckpointStor......

go4it
30分钟前
2
0
makefile 常用函数

Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix程序员。今天我们来学习下makefile的常用函数。 《GNU make》h...

科陆李明
今天
17
0
Android 报错 Could not find com.android.tools.build:aapt2:3.2.1-4818971.

报错信息: Could not find com.android.tools.build:aapt2:3.2.1-4818971.Searched in the following locations: file:/C:/Users/96110/AppData/Local/Android/Sdk/extras/m2reposito......

lanyu96
今天
9
0
我的Linux系统九阴真经

我的Linux系统九阴真经 在今天,互联网的迅猛发展,科技技术也日新月异,各种编程技术也如雨后春笋一样,冒出尖来了。各种创业公司也百花齐放百家争鸣,特别是针对服务行业,新型互联网服务行...

linuxCool
今天
34
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部