本篇文章将延续上篇文章的思路继续完善线程池执行功能,主要完善execute方法线程安全的前提下去除同步锁和对任务执行异常的处理,上篇文章最终代码如下:
@Override
public void execute(Runnable command) {
// 校验参数有效性
if (command == null)
throw new NullPointerException("command is null ...");
// 如果实际线程数量小于核心线程数,
if (getWorkCount() < coreThreadPool)
// 初始化线程执行任务
addThread(command);
else if (workQueue.offer(command)) {
// 任务放入队列成功,校验核心线程是否为0
if (getWorkCount() == 0)
// 初始化一条不携带任务的线程,让它从队列中获取任务
addThread(null);
} else if (getWorkCount() < maxThreadPool) {
// 初始化非核心线程
addThread(command);
} else if (getWorkCount() >= maxThreadPool)
// 提交任务过多,线程池处理过不来,抛出异常
throw new RejectedExecutionException(
"command id too much, reject execute ...");
}
private synchronized void addThread(Runnable task) {
// 由于execute方法调用addThread(null),此处参数非空校验得去掉
// 去掉不保证会有代码恶意调用,所以此方法不能泄露,必须用private修饰
// 为保证代码健壮性,常规参数校验
// if (task == null)
// throw new NullPointerException("taks is null ...");
// 增加一条线程
increaseWork();
new Worker(task).thread.start();
}
// 提供getTask方法从队列中取值
private Runnable getTask() {
boolean timeOut = false;
for (;;) {
boolean timed = getWorkCount() > coreThreadPool;
// 利用timed和timeOut一起判断线程是否应该死亡
if (timed && timeOut) {
// 线程即将死亡,wc自减1
decreaseWork();
// 返回为空意味着跳出while循环,线程即将死亡
return null;
}
try {
// 从队列中取值
Runnable task = timed ? workQueue.poll(keepAliveTime,
TimeUnit.NANOSECONDS) : workQueue.take();
if (task != null)
return task;
// 非核心线程获取超时,直接返回null,跳到循环初始处再次和
// timed变量判断,防止核心线程死亡
timeOut = true;
} catch (