参考Howj、易百教程、Java线程池全面解析、Java线程池使用详解、Java线程池详解
不明白欢迎评论区留言讨论,共同学习。
一、何为线程池
线程池的思路和生产者消费者模型是很接近的。
- 准备一个任务容器
- 一次性启动10个 消费者线程
- 刚开始任务容器是空的,所以线程都wait在上面。
- 直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒notify
- 这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
- 如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行这些任务。
在整个过程中,都不需要创建新的线程,而是循环使用这些已经存在的线程。
之所以不每次都新建线程,这个是因为新建线程会消耗一部分系统资源,如果有大量小任务需要执行,每次都新建大量新线程,会浪费很多系统资源。
二、使用基本线程池
1、线程池类ThreadPoolExecutor简要讲解
线程池类ThreadPoolExecutor
在包java.util.concurrent
下
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- 第一个参数
corePoolSize
:10 表示这个线程池初始化了10个线程在里面工作 - 第二个参数
maximumPoolSize
:15 表示如果10个线程不够用了,就会自动增加,最多增加至15个线程 - 第三个参数
keepAliveTime
:60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,多出来的线程还没有接到活儿,就会回收,最后保持池子里就10个 - 第四个参数
unit
:设置 keepAliveTime 的时间单位,一般用TimeUnit.SECONDS - 第五个参数
workQueue
:工作队列(后面有详解) - 第六个参数
threadFactory
:创建线程的工厂,一般用默认即可。(源码中,若没有填写,默认为Executors.defaultThreadFactory()
,网上其他文章此处多为填写new RecorderThreadFactory("CookieRecorderPool")
- 第七个参数
handler
:拒绝策略,当工作队列、线程池全已满时如何拒绝新任务,默认抛出异常(后面有详解),若需要添加参数可写为new ThreadPoolExecutor.AbortPolicy()
文档中ThreadPoolExecutor有以下方法
可看到,ThreadPoolExecutor有两个方法添加新任务:submit
和 excute
submit和execute分别有什么区别呢?
execute
没有返回值,如果不需要知道线程的结果就使用execute方法,性能会好很多。
submit
返回一个Future对象,如果想知道线程结果就使用submit提交,而且它能在主线程中通过Future的get方法捕获线程中的异常。
我们编写一个简单的用例来进行试验:初始化线程为1、最大线程均为1、队列为LinkedBlockingQueue类型的无界队列(关于队列的解释,请看后文)。至于threadFactory
和handler
的参数,都是默认的参数,此处仅是为了演示如何填写参数。
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,
2,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
threadPool.execute(new Runnable(){
@Override
public void run() {
int i = 0;
while (i < 10) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("任务1 i = %d %n", i);
i++;
}
}
});
threadPool.execute(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep