Java线程池
线程池的作用
管理线程,防止线程频繁的创建或销毁带来的性能消耗
##核心类 ThreadPoolExecutor
源码分析(实现原理)
成员变量
//控制线程池状态,前3位是状态,后29位是RUNNING状态的线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//29
private static final int COUNT_BITS = Integer.SIZE - 3;
//容量
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
/** 常量,运行状态
SHUTDOWN = 0
RUNNING < 0
STOP、TIDYING、TERMINATED > 0
*/
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
private boolean compareAndDecrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect - 1);
}
private void decrementWorkerCount() {
do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}
//阻塞队列
private final BlockingQueue<Runnable> workQueue;
//锁
private final ReentrantLock mainLock = new ReentrantLock();
//存放worker
private final HashSet<Worker> workers = new HashSet<Worker>();
private final Condition termination = mainLock.newCondition();
private int largestPoolSize;
private long completedTaskCount;
private volatile ThreadFactory threadFactory;
private volatile RejectedExecutionHandler handler;
private volatile long keepAliveTime;
private volatile boolean allowCoreThreadTimeOut;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
//拒绝策略
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");
线程池状态
RUNNING:运行态,新建ThreadPoolExecutor实例后线程池就是此状态,可以添加新的任务,也可以对阻塞队列中的任务进行处理。
SHOWDOWN:关闭态,当调用showdown()方法后,线程池进入关闭态,不能接受新的任务,但是可以对阻塞队列中的任务进行处理。
STOP:停止态,调用shutdownNow()方法后,线程池进入停止状态,不能接受新任务,不能对阻塞队列中的任务进行处理。
TIDYING:整理态,所有任务已经终止,ctl的任务数量为0时,线程池进入整理态,会执行函数terminated()函数,如果用户想在TIDYING状态进行处理,可以重载terminated()函数来实现。
TERMINATED:终止态,线程池彻底终止,生命周期结束。
构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
可以看出,前三个构造函数都调用了最后一个。
corePoolSize 核心线程数
maximumPoolSize 最大线程数
keepAliveTime 线程没有执行任务时存活时间
unit 单位
workQueue 阻塞队列,对应排队策略,有以下三种选择
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
threadFactory 线程工厂
拒绝策略
handler 拒绝任务的策略,有以下选择
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,默认handler。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
execute()方法源码分析
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//小于核心线程数,增加线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//如果线程池运行中,加入等待队列
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//recheck下线程池状态,如果非运行,移除刚添加的线程,执行拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
//如果线程池运行,创建worker执行任务(考虑到线程可能挂掉)
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//直接创建Worker来执行任务
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
//使用自旋+cas失败重试来保证线程竞争问题
for (;;) {
//先获取线程池的状态
int c = ctl.get();
int rs = runStateOf(c);
// 如果线程池是关闭的,或者workQueue队列为空,就直接返回false,不做任何处理
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
//根据入参core 来判断可以创建的worker数量是否达到上限,如果达到上限了就拒绝创建worker
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//没有的话就尝试修改ctl添加workerCount的值。这里用了cas操作,如果失败了下一个循环会继续重试,直到设置成功
if (compareAndIncrementWorkerCount(c))
//如果设置成功了就跳出外层的那个for循环
break retry;
//重读一次ctl,判断如果线程池的状态改变了,会再重新循环一次
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
final ReentrantLock mainLock = this.mainLock;
//创建一个worker,将提交上来的任务直接交给worker
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
//加锁,防止竞争
mainLock.lock();
try {
int c = ctl.get();
int rs = runStateOf(c);
//还是判断线程池的状态
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//如果worker的线程已经启动了,会抛出异常
if (t.isAlive())
throw new IllegalThreadStateException();
//添加新建的worker到线程池中
workers.add(w);
int s = workers.size();
//更新历史worker数量的最大值
if (s > largestPoolSize)
largestPoolSize = s;
//设置新增标志位
workerAdded = true;
}
} finally {
mainLock.unlock();
}
//如果worker是新增的,就启动该线程
if (workerAdded) {
t.start();
//成功启动了线程,设置对应的标志位
workerStarted = true;
}
}
} finally {
//如果启动失败了,会触发执行相应的方法
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
Executors提供的线程池及Demo
newFixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
使用
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolUsage {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int ii = i;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " " + ii);
});
}
}
}
pool-1-thread-1 0
pool-1-thread-3 2
pool-1-thread-2 1
pool-1-thread-1 3
pool-1-thread-3 4
pool-1-thread-1 6
pool-1-thread-2 5
pool-1-thread-1 8
pool-1-thread-3 7
pool-1-thread-2 9
三个线程完成10个任务
newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
使用
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolUsage {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int ii = i;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " " + ii);
});
}
}
}
pool-1-thread-1 0
pool-1-thread-1 1
pool-1-thread-1 2
pool-1-thread-1 3
pool-1-thread-1 4
pool-1-thread-1 5
pool-1-thread-1 6
pool-1-thread-1 7
pool-1-thread-1 8
pool-1-thread-1 9
newCachedThreadPool()
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
使用
package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolUsage {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int ii = i;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " " + ii);
});
}
}
}
pool-1-thread-2 1
pool-1-thread-1 0
pool-1-thread-3 2
pool-1-thread-4 3
pool-1-thread-3 8
pool-1-thread-1 7
pool-1-thread-2 9
pool-1-thread-5 4
pool-1-thread-6 5
pool-1-thread-7 6
可以看出,线程池创建了7个线程来执行这10个任务
newScheduledThreadPool()
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
使用
package concurrent;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolUsage {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
pool.schedule(() -> {
System.out.println("延时任务,延时2s");
},2, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(() -> {
System.out.println("延时任务,每两秒执行一次");
}, 1, 2, TimeUnit.SECONDS);
pool.execute(() -> {
System.out.println("普通任务");
});
}
}
普通任务
延时任务,每两秒执行一次
延时任务,延时2s
延时任务,每两秒执行一次
...
除了jdk实现好的线程池,我们也可以根据需要自己创建线程池。另外,有些公司的规范不允许使用以上4种线程池。
Created by lcy on 2020-09-24
Update on 10-09