曹耘豪的博客

Java并发之线程池

  1. 构造函数的参数
    1. corePoolSize
    2. maximumPoolSize
    3. keepAliveTime,unit
    4. workQueue
    5. threadFactory
    6. handler
  2. 内部状态ctl字段
  3. execute方法
  4. getTask方法
  5. runWorker方法
  6. submit方法
    1. FutureTask

本文主要介绍ThreadPoolExecutor

构造函数的参数

corePoolSize

核心线程个数

maximumPoolSize

最大线程个数

keepAliveTime,unit

非核心线程个数超时时间及单位

workQueue

任务队列

threadFactory

线程工厂。主要用于自定义线程name

handler

拒绝策略。当线程数已达最大且任务队列满了触发策略。内置4种拒绝策略,也可以自定义

内部状态ctl字段

使用32位int保存线程池状态(3位)和线程数(29位)

线程池状态有5个:

execute方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
// 线程数小于corePoolSize,添加核心线程
if (addWorker(command, true))
return;
// 如果添加失败,说明ctl有变更,核心线程可能满了
c = ctl.get();
}

if (isRunning(c) && workQueue.offer(command)) {
// 任务加入队列成功
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
// 没有运行且从队列中移除成功,触发拒绝策略
// 移除失败说明已经被worker取走了,已经完成或正在执行,不能触发拒绝策略
reject(command);
else if (workerCountOf(recheck) == 0)
// 没有线程,添加非核心线程,但不分配任务,因为任务已经添加到队列
addWorker(null, false);
}
else if (!addWorker(command, false))
// 队列满了,且添加新线程失败,触发拒绝策略
reject(command);
}

getTask方法

从队列里获取下一个任务

runWorker方法

submit方法

execute的参数是RunnableRunnable并没有返回值,无法直接获取执行的结果,而submit的参数Callable是有返回值的,submit返回Future,包含Callable的返回值

1
2
3
4
5
6
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}

比较简单,将Callable<T>包装成Runnable传给execute,而newTaskFor就是新建一个FutureTask

FutureTask
   / 
  ,