文档章节

ThreadPoolExecutor执行过程分析

4rnold
 4rnold
发布于 06/23 23:47
字数 2237
阅读 7
收藏 1
点赞 0
评论 0

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
博文 49
码字总数 21672
作品 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
线程池之工作原理

流泪撒种的,必欢呼收割。---诗 126:5 最近完成一个功能,当手机板温到达一定值时,触发系统弹出一个警示框,提示用户手机温度过高,系统自动采取降温措施,可能会引起系统流畅性降低,屏幕变...

小草凡
2017/11/22
0
0
JAVA线程池shutdown和shutdownNow的区别

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

Zero零_度
2015/12/18
24
0
Volley为何不用ThreadPoolExecutor

很多人看过Volley的源码,会有一个困惑,执行网络通信操作的4个线程是用数组管理的,没有用到ThreadPoolExecutor。 贴代码RequestQueue.start(),这是网络请求的起始点: public void start(...

指尖上的开源
2015/08/17
0
0
Java并发编程 -- Executor 框架介绍

前面详细通过源码解释了ThreadPoolExecutor类的运行原理,本篇文章来说一下Executor的框架组成。 Java的线程既是工作单元也是执行单元,从JDK5开始,把工作单元与执行机制分离开来,工作单元...

GordonNemo
03/13
0
0
引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用

引用 【轰隆隆】 的 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用 来源:YidingHe's Blog 从 Java 5 开始,Java 提供了自己的线程池。线程池就是一个线程的容器,每次只执行额...

junsun
2010/10/16
0
1
Timer和ScheduledThreadPoolExecutor的定时任务

1 目录 - Timer和ScheduledThreadPoolExecutor的定时任务 2 调度概述 - 1 说到调度,有最简单的Timer、ScheduledThreadPoolExecutor,又有Spring Task、quartz。 - 2 说到分布式调度,有基于...

乒乓狂魔
2016/09/12
189
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
14分钟前
0
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
27分钟前
14
0
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
39分钟前
0
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
45分钟前
0
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
59分钟前
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
今天
0
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
今天
0
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
今天
0
0
安装tensorflow-XXX报错

报错: tensorflow-0.5.0-cp27-none-linux_x86_64.whl is not a supported wheel on this platform. 解决: wget https://bootstrap.pypa.io/get-pip.py sudo python2.7 get-pip.py sudo p......

Yao--靠自己
今天
0
0
JVM学习手册(一):JVM模型

一直从事JAVA开发,天天和JVM打交道,仔细想想对JVM还真的不是特别了解,实在是不应该.周六看了许多资料,也算有点心得,记录一下。 JVM内存模型分为5个区域:方法区,堆,虚拟机栈,本地方法栈,程序计...

勤奋的蚂蚁
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部