也来分析下Java 线程池(ThreadPoolExecutor)的原理
来源:互联网 发布:云服务器ecs绑定域名 编辑:程序博客网 时间:2024/06/06 18:55
先提几个问题:
1.线程池的工作原理是啥?
2.核心线程池是一开始时就创建够吗?空闲时核心线程池也一直维持不变吗?
3.线程池是如何被停止的?
如果你都能非常自信地回答出来,那后面的内容可以不用看了。
参考文章:
《Java 线程池(ThreadPoolExecutor)原理分析与使用》
一、线程池的使用
1.创建线程池:
通过new创建,构造函数为:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
2.提交任务:
public void execute(Runnable command)
3.关闭线程池:
1.public void shutdown()
2.public List shutdownNow()
两个方法的区别:
shutdown方法是尝试将所有空闲线程intrupt掉;而shutdownNow是将所有活动中的线程以及空闲线程都intrupt掉。
二、实现原理
三、原理分析
1.用来充当线程池的是一个数组:private final HashSet workers;
2.每个提交的任务都是一个Runnable,进入线程池后,会被包装成为一个 Worker;
3.Worker类是个内部类,自身实现了Runnable接口。它有两个成员变量:
Thread thread,Runnable firstTask,Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this);}/** Delegates main run loop to outer runWorker. */public void run() { runWorker(this);}
从代码里可以看出,Worker在创建线程Thread时,用的是自身;而不是原始的任务firstTask,这样一来,就得到了干预线程执行的机会。
4.在runWorker方法的主要代码如下:
task = w.firstTask;try{ while (task != null || (task = getTask()) != null){ task.run(); }} finally { processWorkerExit(w, completedAbruptly);}
5.在addWorker方法中,做了两件事:创建线程并执行;即:
1.根据Runnable创建Worker对象;
2.将Worker对象存入数组workers中;
3.执行Worker对象里的thread;
6.根据线程的实现,我们知道t.start()的执行最终会调用Runnable里的run方法;由此可知在addWorker方法执行线程,最终会走到runWorker方法里来;
7.从runWorker方法的实现可以看到,每个入参Worker中的线程在完成自身的firstTask任务之后,还要继续去完成队列中的任务;
8.在runWorker方法中,当执行完所有的任务或者当执行完一个任务后发现线程已被中断,则会跳出循环,调用processWorkerExit方法来自动终结自己。
9.processWorkerExit方法里主要做了两件事:
1.将入参worker从数组workers里删除掉;
2.根据布尔值allowCoreThreadTimeOut来决定是否补充新的Worker进数组workers,方法为:
addWorker(null, false);
意思为只新增线程,无初始的任务。
回答前面的问题
1.线程池的工作原理是啥?
答:见原理图,先coresize,再queue队列,再maxsize,最后RejectedExecutionHandler。
2.核心线程池是一开始时就创建够吗?空闲时核心线程池也一直维持不变吗?
答:不是的,线程池是逐一增加至核心线程数的。不过可以通过executor提供的一些方法来直接将线程池预热至核心线程数。如方法:
public int prestartAllCoreThreads()
空闲时会根据allowCoreThreadTimeOut的值来决定是否要维持核心线程数的线程。该值默认是false,就是要维持核心线程池。可以通过方法来修改该布尔值。
3.线程池是如何被停止的?
答:通过shutdown或者shutdownNow方法来停止线程池。在这两个方法中,都是通过循环将works里每个work的线程进行Thread.interrupt()调用,给线程设置一个的停止标志。线程在自己的run方法中可以通过循环检查.interrupted()方法是否为真,来结束自己。
- 也来分析下Java 线程池(ThreadPoolExecutor)的原理
- Java线程池ThreadPoolExecutor的execute()原理
- Java ThreadPoolExecutor线程池原理及源码分析
- Java线程池(ThreadPoolExecutor)原理分析与使用
- Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网
- Java 线程池(ThreadPoolExecutor)原理分析与使用
- JAVA线程池(ThreadPoolExecutor)原理分析与使用
- Java 线程池(ThreadPoolExecutor)原理分析与使用
- Java 线程池(ThreadPoolExecutor)原理分析与使用
- Java 线程池(ThreadPoolExecutor)原理分析与使用
- Java 线程池(ThreadPoolExecutor)原理分析与使用
- 线程池ThreadPoolExecutor的原理
- Java中的线程池——ThreadPoolExecutor的原理
- java线程池ThreadPoolExecutor原理及使用
- Java中线程池ThreadPoolExecutor原理探究
- Java ThreadPoolExecutor 线程池 tips 1:单线程吞吐量来估计系统的线程数目
- Java ThreadPoolExecutor 线程池 tips 1:单线程吞吐量来估计系统的线程数目
- JAVA线程池(ThreadPoolExecutor)源码分析
- (M)Backtracking:17. Letter Combinations of a Phone Number
- XAMPP安装配置教程(Windows)
- C++学习笔记——函数的参数传递
- 添加STC的MCU進Keil4
- 页面之间的通信
- 也来分析下Java 线程池(ThreadPoolExecutor)的原理
- MyEclipse快捷键有参构造和无参构造
- 一些工具的安装
- 数据加密
- css的伪类和伪元素
- linux mint:关于解决安装中文输入法之后字体变化的问题
- C++学习过程笔记(1)
- window.name
- 学习各种动画,效果等,掌握其实现原理