线程池理解

线程池

线程池本质上是一种对象池,用于管理线程资源,实现线程的复用
优点

  • 降低资源消耗(通过复用降低线程重复创建和销毁)
  • 提高响应速度(任务到达就立即执行)
  • 提高线程的可管理性(线程池进行统一的分配、调优和监控)

体系结构

在这里插入图片描述

Executor

执行提交的Runnable任务

public interface Executor {
    void execute(Runnable command);
}
ExecutorService

继承自Executor,提供方法来管理终端和方法,可以产生Future跟踪一个或多个异步任务执行。

public interface ExecutorService extends Executor {
	//执行一批任务,任务执行完成才返回,如果出现异常则取消所有任务执行
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
	//启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务
	void shutdown();
	//尝试停止所有主动执行的任务,停止等待任务的处理,并返回正在等待执行的任务列表
	List<Runnable> shutdownNow();
	//提交值返回任务以执行,并返回代表任务待处理结果的Future
	<T> Future<T> submit(Callable<T> task);
	//提交一个可运行的任务执行,并返回一个表示该任务的未来
	Future<?> submit(Runnable task);
}
ScheduledExecutorService

提供调度命令在给定的延迟之后运行,或定期执行的接口

public interface ScheduledExecutorService extends ExecutorService {
	//创建并执行在给定延迟后启用的ScheduledFuture
	public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);
	//创建并执行在给定延迟后启用的单次操作
	public ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit);
	//创建并执行在给定的初始延迟之后,随后以给定的时间段首先启用的周期性动作
	//从上个任务开始计算间隔时间
	public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);
	//建并执行在给定的初始延迟之后首先启用的定期动作,随后在一个执行的终止和下一个执行的开始之间给定的延迟。
	//从上个任务结束开始计算间隔时间
	public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);
}
AbstractExecutorService

提供ExecutorService执行方法的默认实现

public abstract class AbstractExecutorService implements ExecutorService {
	public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        //创建FutureTask
        RunnableFuture<T> ftask = newTaskFor(task);
        //使用线程执行任务
        execute(ftask);
        //返回任务
        return ftask;
    }
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
}

ThreadPoolExecutor

成员变量
//高3位存储线程池状态(默认Running),低29位存储线程数量
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;

// 运行状态,高位存储
//接受新任务,处理阻塞队列
private static final int RUNNING    = -1 << COUNT_BITS;
//不接受新任务,处理阻塞队列
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//不接受新任务,不处理阻塞队列并中断所有在执行中的线程
private static final int STOP       =  1 << COUNT_BITS;
//整理,所有任务都被终结,活跃线程为0,触发terminated方法
private static final int TIDYING    =  2 << COUNT_BITS;
//terminated方法执行完成后的状态
private static final int TERMINATED =  3 << COUNT_BITS;


//构造方法中传入的参数
private final BlockingQueue<Runnable> workQueue;
private volatile ThreadFactory threadFactory;
private volatile RejectedExecutionHandler handler;
private volatile long keepAliveTime;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

//线程池中的同步控制(可重入锁)
private final ReentrantLock mainLock = new ReentrantLock();
private final Condition termination = mainLock.newCondition();

//HashSet管理工作线程
private final HashSet<Worker> workers = new HashSet<Worker>();
//记录了曾经出现的最大线程个数
private int largestPoolSize;
//完成任务数
private long completedTaskCount;
//是否允许核心线程超时
private volatile boolean allowCoreThreadTimeOut;
构造方法
/**
*@corePoolSize:核心线程数,当线程数低于该值优先新建线程
*@maximumPoolSize:线程池中最大线程数
*@keepAliveTime:空闲线程存活时间
*@unit:存活时间单位
*@workQueue:任务队列,缓存待执行任务
*@threadFactory:线程工厂,用来新建线程,defaultThreadFactory默认使用的工厂
*@handler:拒绝策略,当线程池和任务队列都满时使用,AbortPolicy默认拒绝策略
*/
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.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}
内部类
Worker

线程池中的包装类,一个Worker代表一个线程,实现Runnable接口,继承AQS同步器类

private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
	//持有的线程
	final Thread thread;
	//执行的初始任务,创建Worker时赋值
	Runnable firstTask;
	//Worker对象完成的任务数
	volatile long completedTasks;

	Worker(Runnable firstTask) {
		 //设置同步器状态为-1,在执行runWorker方法之前不允许中断
         setState(-1); 
         this.firstTask = firstTask;
         //从线程工厂获得创建的线程
         this.thread = getThreadFactory().newThread(this);
     }

}
线程池的执行
execute

submit方法的执行本质上也是调用execute,只不过是多了Future返回值,能实现异步获得执行结果(执行过程的异常在调用get方法时处理)。

  1. 如果线程数小于核心线程则直接创建线程执行任务
  2. 如果线程数大于等于核心线程则将任务添加到阻塞队列中
  3. 如果阻塞队列已满则创建非核心线程执行任务
public void execute(Runnable command) {
	//如果任务为null抛出异常
    if (command == null)
        throw new NullPointerException();
    //线程池状态和线程数
    int c = ctl.get();
    //当前线程池中任务数小于核心线程数
    if (workerCountOf(c) < corePoolSize) {
    	//启动核心线程并执行任务
        if (addWorker(command, true))
            return;
        //如果执行失败,重新获取状态
        c = ctl.get();
    }
    //如果线程池为Running状态,在阻塞队列中添加任务
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //重新检查池状态,如果不为Running则remove并执行拒绝策略
        if (! isRunning(recheck) && remove(command))
            reject(command);
        //如果线程数为0,创建非核心线程,addWorker(null)表示从阻塞队列中获取任务
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    //队列已满,在队列中添加任务失败则创建非核心线程执行任务
    else if (!addWorker(command, false))
        reject(command);
}
addWorker

新建线程,firstTask:需执行的任务,core:是否为核心线程

返回false的情况:线程池状态,线程数大于规定,任务添加失败(任务线程已被启动或线程池状态改变)

执行过程

  1. 判断线程池状态,大于SHUTDOWN则不执行,当等于SHUTDOWN时,只有当firstTask为null且队列不为空才继续执行(表示不添加新任务只执行队列中存在的任务)
  2. 自旋修改ctl中的线程数,首先判断是否大于核心线程数或最大线程数,然后CAS修改,失败则判断状态是否改变,改变则从外循环重新开始否则在本循环自旋。
  3. 新建任务,同步控制在workers中添加任务,并启动
private boolean addWorker(Runnable firstTask, boolean core) {
    //java中的label标签,用于记录跳出或终止循环的位置
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        //判断线程池状态,>SHUTDOWN不执行添加任务,=SHUTDOWN时firstTask为null且队列不为空才继续执行
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
        	//当前线程池中线程数
            int wc = workerCountOf(c);
            //判断是否大于核心线程或最大线程数
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            //CAS修改线程数
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get();  // 修改失败重新获得ctl
            //ctl状态改变则重新从外层循环开始
            if (runStateOf(c) != rs)
                continue retry;
            //状态未改变则自旋重新CAS修改线程数
        }
    }

	//此时线程数已被修改,开始新建启动线程
    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
    	//创建Worker
        w = new Worker(firstTask);
        final Thread t = w.thread;
        //任务的线程不为null
        if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                
                int rs = runStateOf(ctl.get());
				//重新检查线程状态
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) //如果线程已被启动
                        throw new IllegalThreadStateException();
                    //将Worker加入HashSet
                    workers.add(w);
                    int s = workers.size();
                    //记录线程池持有过的最大线程数
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            //正常添加则启动线程
            if (workerAdded) {
                t.start();
                workerStarted = true;
            }
        }
    } finally {
    	//如果任务启动失败(线程已被启动或线程池状态改变)
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}
private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    	//从HashSet中移除Worker
        if (w != null)
            workers.remove(w);
        //线程数减1
        decrementWorkerCount();
        //尝试终止
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}
runWorker

Worker被start后会调用其run方法,然后会调用ThreadPoolExecutor的runWorker方法。

  1. 如果task为null则从队列中获取task
  2. 线程池处于STOP状态则设置中断,不处于则清除中断
  3. 执行任务直到队列为空
  4. 回收线程,从workers中移除
public void run() {
    runWorker(this);
}
final void runWorker(Worker w) {
	//执行任务的线程
    Thread wt = Thread.currentThread();
    //被执行的任务
    Runnable task = w.firstTask;
    w.firstTask = null;
    //此时Worker的state为-1,unlcok后state为0允许中断
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
    	//任务为空则从队列中取直到队列为空
        while (task != null || (task = getTask()) != null) {
            //同一时间相同的Worker只能被一个线程使用
            w.lock();
			//如果线程池处于STOP状态则设置中断,否则清除中断标识并在此判断状态(防止清除后调用了shutdownNow)
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
            	//执行前方法,空方法由子类实现
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                	//执行任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                	//空方法,由子类实现
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                //当前Worker完成任务数+1
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
    	//执行到此处说明队列中无任务需执行,开始回收线程
        processWorkerExit(w, completedAbruptly);
    }
}
getTask

获得队列中的任务

  1. 如果线程池状态为Stop及以上或状态为Shutdown且队列为空则不再执行返回null
  2. 判断是否启用超时(线程数大于核心线程数或允许核心线程超时)
  3. 当线程数大于最大线程数或获得任务超时并且队列为空或还有其他线程存在则返回null
  4. 从队列中获取任务(poll,take)
private Runnable getTask() {
    boolean timedOut = false; // 表示获取任务是否已超时

    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 如果状态>=STOP或状态为SHUTDOWN且队列为空则减少线程数并返回null
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }
		
		//线程池中线程数量
        int wc = workerCountOf(c);

        //是否启用超时回收空闲线程,线程数大于核心线程或允许核心线程超时为true
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
		//如果线程数大于最大线程数或任务超时并且线程数大于1或队列为空,cas减少线程数,失败则重新循环
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
        	//启用超时使用poll方法,否则使用take方法阻塞直到获得任务
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            //此时获取任务超时
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}
processWorkerExit

出现异常则减少线程数(正常执行已在getTask减少),移除,然后再新建非核心线程继续执行

  1. 如果任务执行过程出现异常,线程数减少
  2. 从workers中删除当前Worker
  3. 出现异常或当前线程池的线程数小于定义的min则新建非核心线程
private void processWorkerExit(Worker w, boolean completedAbruptly) {
    if (completedAbruptly) // 如果任务执行过程出现异常,线程数减少
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    	//从HashSet中移除Worker
        completedTaskCount += w.completedTasks;
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }
	//尝试中断
    tryTerminate();

    int c = ctl.get();
    //如果状态为Running和Shutdown
    if (runStateLessThan(c, STOP)) {
    	//如果任务正常执行完成(队列为空)
        if (!completedAbruptly) {
        	//如果允许移除核心线程,min=0,否则为核心线程数
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            //说明有可用线程在执行队列中的任务
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        //任务执行异常或可用线程小于最小值,添加非核心线程执行队列中的任务
        addWorker(null, false);
    }
}
tryTerminate

尝试结束线程池,processWorkerExit(队列为空或执行出现异常进入)、addWorkerFailed(线程已启动或线程池状态改变进入)中存在

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        //如果线程池状态为running或>=TIDYING或为SHUTDOWN 时队列不为空则不结束
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        //如果线程池中还存在线程也不结束
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	//设置线程状态为TIDYING调用terminated方法
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                	//空方法
                    terminated();
                } finally {
                	//设置线程池状态为TERMINATED
                    ctl.set(ctlOf(TERMINATED, 0));
                    //唤醒所有在TERMINATED等待的线程
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

线程池关闭
shutdown
public void shutdown() {
   final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    	//安全策略检查
        checkShutdownAccess();
        //自旋CAS修改线程池状态
        advanceRunState(SHUTDOWN);
        //所有空闲线程设置中断标识
        interruptIdleWorkers();
        //空方法,ScheduledThreadPoolExecutor使用
        onShutdown();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
}
shutdownNow
public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    	//安全策略检查
        checkShutdownAccess();
        //自旋CAS修改线程池状态
        advanceRunState(STOP);
        //中断所有启动的线程
        interruptWorkers();
        //获得所有在阻塞队列中的任务
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

工具类Executors

内部类
RunnableAdapter

适配器,将Runnable转换为Callable

static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    //实现Callable中call方法:执行Runnable中run方法返回传入的result
    public T call() {
        task.run();
        return result;
    }
}
方法
callable
public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

具体实现类

newFixedThreadPool

构建包含固定线程数的线程池,核心线程数和最大线程数相同,默认情况下,空闲线程不会被回收

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
newSingleThreadExecutor

构建线程数为1的线程池

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
newCachedThreadPool

构建线程数不定的线程池,线程数量随任务量变动,空闲线程存活时间超过60秒后被回收,使用SynchronousQueue同步队列(自旋+CAS+模式),当提交任务速度大小处理任务速度时,每次提交任务都会创建一个线程

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
newScheduledThreadPool

构建核心线程数为 corePoolSize,可执行定时任务的线程池

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值