【并发编程】-- ThreadPoolExecutor线程池执行器

163 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

ThreadPoolExecutor线程池执行器

使用ThreadPoolExecutor线程池代码如下:

public class ThreadPoolExecutorRun {
    public static void main(String[] args) {
        //创建一个核心线程数为1,最大线程数为1,无界队列的线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        //向线程池提交任务
        threadPoolExecutor.submit(()->{
            System.out.println("Gxin"+System.currentTimeMillis());
        });
        //关闭线程池
        threadPoolExecutor.shutdown();
        //等待线程池终止
        try {
            threadPoolExecutor.awaitTermination(1,TimeUnit.HOURS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ThreadPoolExecutor核心数据结构

ThreadPoolExecutor的核心数据结构和变量如下:

public class ThreadPoolExecutor extends AbstractExecutorService {
	//通过一个原子性的integer整型值包含了workerCount工作线程数和runState运行状态
	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
	//统计数量位数COUNT_BITS:32-3=29,所以最大工作线程数为CAPACITY:2^29 - 1,大约有5亿个,足够使用了。
	private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    //上面的一个整数为32位,占用了29位统计数量,剩下的3位高位bit用来作为线程池状态。
    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;

    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 final BlockingQueue<Runnable> workQueue;
    private final ReentrantLock mainLock = new ReentrantLock();
    private final HashSet<Worker> workers = new HashSet<Worker>();
    
}

解析方法如下:

runState提供了主要的生命周期控件,线程运行的状态变化,其值如下:

RUNNING:接收新任务并处理排队的任务。

SHUTDOWN:不接收新任务,但处理已排队的任务。

STOP:不接收新任务,不处理排队的任务,中断正在进行的任务。

TIDYING:所有的任务已经停止,workerCount为零,当线程过渡到TIDYING状态时,将运行terminated()钩子方法。

TERMINATED:TERMINATED()已经执行完成。

runStateOf(int c)、workerCountOf(int c)、ctlOf(int rs, int wc):3个函数用来从ctl整型变量中获取对应的状态或者线程数。

workQueue:用于缓存提交到线程池的任务队列,注意点是队列类型是BlockingQueue,证明了多线程操作是安全的,毕竟是生产者消费者模式,外部线程producer,内部线程consumer。

ReentrantLock():用于保护全局互斥资源的可重入锁。

new HashSet()方法:用于保存所有线程池中的Worker对象的set集合,可以看出这并不是线程安全的结构,所以在多线程中访问这个集合需要通过上面的mainLock上锁后访问,保证线程安全。