ThreadPoolExecutor 介绍

简写:

  1. package com.vipsoft.Thread;
  2.  
  3. import java.util.concurrent.*;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5.  
  6. public class ThreadPoolExecutorTest {
  7.  
  8. public static void main(String[] args) throws Exception {
  9. ThreadPoolExecutor executor = new ThreadPoolExecutor(
  10. 2,
  11. 4,
  12. 10L,
  13. TimeUnit.SECONDS,
  14. new LinkedBlockingQueue<Runnable>(2),
  15. new ThreadFactory() {
  16. private final AtomicInteger mThreadNum = new AtomicInteger(1);
  17.  
  18. @Override
  19. public Thread newThread(Runnable r) {
  20. Thread t = new Thread(r, "Thread-" + mThreadNum.getAndIncrement());
  21. System.out.println(t.getName() + " has been created");
  22. return t;
  23. }
  24. },
  25. new RejectedExecutionHandler() {
  26. @Override
  27. public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
  28. // 可做日志记录等
  29. System.err.println(r.toString() + " rejected " + executor.getTaskCount());
  30. }
  31. });
  32.  
  33. executor.prestartAllCoreThreads(); // 预启动所有核心线程
  34.  
  35. for (int i = 1; i <= 10; i++) {
  36. final String taskName = String.valueOf(i);
  37. executor.execute(new Runnable() {
  38. @Override
  39. public void run() {
  40. try {
  41. System.out.println(this.toString() + " is running!");
  42. Thread.sleep(3000); //让任务执行慢点
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47.  
  48. @Override
  49. public String toString() {
  50. return "MyTask [name=" + taskName + "]";
  51. }
  52. });
  53. }
  54.  
  55. //可读性好些
  56. // Runnable call = new Runnable() {
  57. // @Override
  58. // public void run() {
  59. // try {
  60. // System.out.println(this.toString() + " is running!");
  61. // Thread.sleep(3000); //让任务执行慢点
  62. // } catch (InterruptedException e) {
  63. // e.printStackTrace();
  64. // }
  65. // }
  66.  
  67. // @Override
  68. // public String toString() {
  69. // return "MyTask [name=" + taskName + "]";
  70. // }
  71. // }
  72.  
  73. // for (int i = 1; i <= 10; i++) {
  74. // final String taskName = String.valueOf(i);
  75. // executor.execute(call);
  76. // }
  77.  
  78. System.in.read(); //阻塞主线程
  79. }
  80.  
  81. }

常规写法:

  1. package com.vipsoft.Thread;
  2.  
  3. import java.util.concurrent.*;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5.  
  6. public class ThreadPoolExecutorTest {
  7.  
  8. public static void main(String[] args) throws Exception {
  9. int corePoolSize = 2;
  10. int maximumPoolSize = 5;
  11. long keepAliveTime = 10;
  12. TimeUnit unit = TimeUnit.SECONDS;
  13. BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(3); //定义一个大小为2的队列,只等有一个任务在排队等,多出来的需要开新线程
  14. ThreadFactory threadFactory = new MyTreadFactory();
  15. RejectedExecutionHandler handler = new MyPolicy();
  16. ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
  17. System.out.println("预启动线程(备战)");
  18. executor.prestartAllCoreThreads(); // 预启动所有核心线程,处于备战
  19. System.out.println("预启动线程数(备战):" + executor.getPoolSize());
  20. for (int i = 1; i <= 10; i++) {
  21. System.out.println(System.currentTimeMillis() + " " + "开始 下发任务:" + i + " 当前线程总数:" + executor.getPoolSize());
  22. MyTask task = new MyTask(String.valueOf(i));
  23. executor.execute(task);
  24. System.out.println(System.currentTimeMillis() + " " + "完成 下发任务:" + i + " 当前线程总数:" + executor.getPoolSize() + " 队列中的线程数量:" + workQueue.size());
  25. Thread.sleep(1); //停1毫秒,日志记录,时间后方便分析
  26. if (i == 9) {
  27. //TODO Thread.sleep(3000); //任务9下发后【会被拒绝】,停3秒,等队列或线程释放后,再下发任务10,这时候任务10不会被拒绝
  28. }
  29. }
  30. System.in.read(); //阻塞主线程
  31. }
  32.  
  33. static class MyTreadFactory implements ThreadFactory {
  34.  
  35. private final AtomicInteger mThreadNum = new AtomicInteger(1);
  36.  
  37. @Override
  38. public Thread newThread(Runnable r) {
  39. Thread t = new Thread(r, "Thread-" + mThreadNum.getAndIncrement());
  40. System.out.println(System.currentTimeMillis() + " " + t.getName() + " has been created");
  41. return t;
  42. }
  43. }
  44.  
  45. public static class MyPolicy implements RejectedExecutionHandler {
  46.  
  47. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
  48. // 可做日志记录等
  49. System.err.println(System.currentTimeMillis() + " " + r.toString() + " rejected from " + e.toString());
  50. }
  51. }
  52.  
  53. static class MyTask implements Runnable {
  54. private String name;
  55.  
  56. public MyTask(String name) {
  57. this.name = name;
  58. }
  59.  
  60. @Override
  61. public void run() {
  62. try {
  63. System.out.println(System.currentTimeMillis() + " " + this.toString() + " 开始运行! " + Thread.currentThread().getName());
  64. Thread.sleep(3000); //让任务执行慢点
  65. System.out.println(System.currentTimeMillis() + " " + this.toString() + " 运行结束! " + Thread.currentThread().getName());
  66. } catch (InterruptedException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70.  
  71. @Override
  72. public String toString() {
  73. return "MyTask [name=" + this.name + "]";
  74. }
  75. }
  76. }

运行结果:忽略图片内容

将日志按时间排序后解读:可容纳任务数 = 最大线程数 + 最大队列数

  1. 预启动线程(备战)
  2. 预启动线程数(备战):2
  3. 1654760985275 Thread-1 has been created //预启动创建线程
  4. 1654760985275 Thread-2 has been created //预启动创建线程
  5. 1654760985275 开始 下发任务:1 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  6. 1654760985276 MyTask [name=1] 开始运行! Thread-2
  7. 1654760985276 完成 下发任务:1 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  8. 1654760985278 MyTask [name=2] 开始运行! Thread-1
  9. 1654760985278 开始 下发任务:2 当前线程总数:2
  10. 1654760985278 完成 下发任务:2 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  11. 1654760985280 开始 下发任务:3 当前线程总数:2
  12. 1654760985280 完成 下发任务:3 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  13. 1654760985282 开始 下发任务:4 当前线程总数:2
  14. 1654760985282 完成 下发任务:4 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  15. 1654760985284 开始 下发任务:5 当前线程总数:2
  16. 1654760985284 完成 下发任务:5 当前线程总数:2 //下发任务,当前有2线程(预启动创建)
  17. 1654760985286 MyTask [name=6] 开始运行! Thread-3
  18. 1654760985286 Thread-3 has been created
  19. 1654760985286 开始 下发任务:6 当前线程总数:2
  20. 1654760985286 完成 下发任务:6 当前线程总数:3 //下发任务,当前有2线程,3个队列,第6个任务,已经不够放了,新建一个线程
  21. 1654760985288 MyTask [name=7] 开始运行! Thread-4
  22. 1654760985288 Thread-4 has been created
  23. 1654760985288 开始 下发任务:7 当前线程总数:3
  24. 1654760985288 完成 下发任务:7 当前线程总数:4 //下发任务,当前有3线程,3个队列,第8个任务,已经不够放了,新建一个线程
  25. 1654760985290 MyTask [name=8] 开始运行! Thread-5
  26. 1654760985290 Thread-5 has been created
  27. 1654760985290 开始 下发任务:8 当前线程总数:4
  28. 1654760985290 完成 下发任务:8 当前线程总数:5 //下发任务,当前有4线程,3个队列,第8个任务,已经不够放了,新建一个线程
  29. 1654760985292 MyTask [name=9] rejected from java.util.concurrent.ThreadPoolExecutor@4b1210ee[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
  30. 1654760985292 开始 下发任务:9 当前线程总数:5
  31. 1654760985292 完成 下发任务:9 当前线程总数:5 //下发任务,当前有5线程,3个队列,第9个任务,已经不够放了,新建一个线程(超过了最大线程数 maximumPoolSize + 队列数 workQueue )拒绝任务9
  32. 1654760985294 MyTask [name=10] rejected from java.util.concurrent.ThreadPoolExecutor@4b1210ee[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
  33. 1654760985294 开始 下发任务:10 当前线程总数:5
  34. 1654760985294 完成 下发任务:10 当前线程总数:5 //下发任务,当前有5线程,3个队列,第10个任务,已经不够放了,新建一个线程(超过了最大线程数+队列数)拒绝任务10
  35. 1654760988276 MyTask [name=1] 运行结束! Thread-2 //等有任务结束后,再去下发任务9、10,就不会抛弃任务了
  36. 1654760988276 MyTask [name=3] 开始运行! Thread-2
  37. 1654760988278 MyTask [name=2] 运行结束! Thread-1
  38. 1654760988278 MyTask [name=4] 开始运行! Thread-1
  39. 1654760988286 MyTask [name=5] 开始运行! Thread-3
  40. 1654760988286 MyTask [name=6] 运行结束! Thread-3
  41. 1654760988288 MyTask [name=7] 运行结束! Thread-4
  42. 1654760988291 MyTask [name=8] 运行结束! Thread-5
  43. 1654760991288 MyTask [name=3] 运行结束! Thread-2
  44. 1654760991288 MyTask [name=4] 运行结束! Thread-1
  45. 1654760991288 MyTask [name=5] 运行结束! Thread-3

ThreadPoolExecutor 使用的更多相关文章

  1. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  2. 并发包的线程池第一篇--ThreadPoolExecutor执行逻辑

    学习这个很长时间了一直没有去做个总结,现在大致总结一下并发包的线程池. 首先,任何代码都是解决问题的,线程池解决什么问题? 如果我们不用线程池,每次需要跑一个线程的时候自己new一个,会导致几个问题: ...

  3. ThreadPoolExecutor源码学习(1)-- 主要思路

    ThreadPoolExecutor是JDK自带的并发包对于线程池的实现,从JDK1.5开始,直至我所阅读的1.6与1.7的并发包代码,从代码注释上看,均出自Doug Lea之手,从代码上看JDK1. ...

  4. ThreadPoolExecutor源码学习(2)-- 在thrift中的应用

    thrift作为一个从底到上除去业务逻辑代码,可以生成多种语言客户端以及服务器代码,涵盖了网络,IO,进程,线程管理的框架,着实庞大,不过它层次清晰,4层每层解决不同的问题,可以按需取用,相当方便. ...

  5. Java 线程 — ThreadPoolExecutor

    线程池 线程池处理流程 核心线程池:创建新线程执行任务,需要获取全局锁 队列:将新来的任务加入队列 线程池:大于corePoolSize,并且队列已满,小于maxPoolSize,创建新的worker ...

  6. java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。

    转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...

  7. 【JUC】JDK1.8源码分析之ThreadPoolExecutor(一)

    一.前言 JUC这部分还有线程池这一块没有分析,需要抓紧时间分析,下面开始ThreadPoolExecutor,其是线程池的基础,分析完了这个类会简化之后的分析,线程池可以解决两个不同问题:由于减少了 ...

  8. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  9. java线程池ThreadPoolExecutor理解

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  10. java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f303192 rejected from java.util.concurrent.ThreadPoolExecutor@11f7cc04[Terminated, pool size = 0, active threads

    java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1f303192 rejec ...

随机推荐

  1. SpringBoot系列之MyBatis Plus自动填充实现

    系列博客专栏:SpringBoot2.0系列博客专栏 开发环境 JDK 1.8 SpringBoot2.2.1 Maven 3.2+ Mysql5.7.36 开发工具 IntelliJ IDEA sm ...

  2. 树莓派4b部署samba服务实现文件共享

    注意 samba 生命力很旺盛,软件是在不断更新的, 网上很多针对 samba 网速优化设置截止当前 实测发现有很多已经过期, 甚至有些设置会适得其反,使传输速度更低. 例如, 全网都在配置的参数,& ...

  3. ReverseMe-120

    一道好题,没解出来但是收获很多 贴两位大牛的题解 [精选]攻防世界逆向高手题之ReverseMe-120-CSDN博客 攻防世界ReverseMe-120详解_攻防世界reverseme基本思路-CS ...

  4. 解密Spring Cloud微服务调用:如何轻松获取请求目标方的IP和端口

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 目的 Spring Cloud 线上微服务实例都是2个起步,如果出问题后,在没有ELK等日志分析平台,如何确定调用到了目标 ...

  5. 一文带你掌握C语言的分支结构

    C语言分支结构详解 1. if 语句 在本篇博客文章中,我们将深入探讨C语言中的if语句及其相关用法.if语句是一种用于条件判断的分支语句,它允许我们根据条件的真假来执行不同的代码块. 1.1 if ...

  6. git推送时报错:fatal: unable to access 'https://github.com/xxx/xxx.git/': Failed to connect to 127.0.0.1 port 31181 after 2063 ms: Connection refused

    一.报错原因 1.因为git在拉取或者提交项目时,中间会有git的http和https代理,但是我们本地环境本身就有SSL协议了,所以取消git的https代理即可,不行再取消http的代理. 2.当 ...

  7. GOF23--23种设计模式(一)

    一.什么是设计模式 设计模式(Design  Pattern)是前辈们对代码开发经验的总结,是解决一系列特定问题的套路. 它不是语法规定,而是一套用来提高代码复用性,可读性,可维护性,稳健性,安全性的 ...

  8. [ARC137E] Baker

    Problem Statement Snuke runs a bakery. He is planning for the next $N$ days. Let us call these days ...

  9. int和String的相互转换

  10. DEDECMS 后台系统用户授权目录更改为无限级(默认为二级授权)

    在做一个学校的项目,分类有四级分类,总共一百多个分类,因为每个分类对应不同的老师,用于上传资料作为考核,但是添加系统用户的时候发现DEDECMS只有两级分类,所以修改啦一些代码,目前不知道是否修改完全 ...