线程池源码剖析(创建,复用,超时处理)

在jdk1.5后,官方为我们实现了线程池ThreadPoolExecutor,通过该线程池,我们可以一次性(其实并非一次性,而是慢慢的添加线程,直到线程池满)的预先执行代价高昂的线程分配,而且所有分配的线程都是可重用的。下面我们将会根据Executors.newFixedThreadPool为切入口分析以下线程池的创建过程和线程池的线程分配问题。

当我们执行Executors.newFixedThreadPool时,我们一直跟进构造这个方法的内部,可以发现它其实是调用了ThreadPoolExecutor的构造函数:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
ThreadPoolExecutor为线程池对象,负责构建恰当的上下文来执行Runnable对象,同时负责管理所有它创建的线程的生命周期。在这个构造函数中,我们只要关注两个参数。nThreads代表的线程池的核心的线程数量(还有一个最大线程数量,这里和核心线程数量保持了一致),LinkedBlockingQueue阻塞队列对象则用来管理所有的任务并且将任务提交给工作线程(只有在当前线程池已满的情况下,才回将一个task放入阻塞队列)。

构造方法执行完成后,我们将得到一个ThreadPoolExecutor对象。注意,此时该对象不会开启任何线程。该对象中有一个重要的属性,分别如下:

1.private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
该字段代表线程池的控制状态,这个字段有两个概念上的属性:1.workercount(代表有效的线程的数量);2.runState(代表线程池的工作状态,running, shutting down etc)。
2.private final BlockingQueue<Runnable> workQueue;
用于存放task,并将task提交给工作线程(上面的阻塞队列参数注入位置)

3.private final HashSet<Worker> workers = new HashSet<Worker>();
代表所有工作任务的集合。Woker是一个继承了Runnable的类,内部有两个属性final Thread thread和Runnable firstTask,当要开启一个线程时,就会通过worker.get thread获取该内部创建的线程(由于该thread对象创建时,worker将自身通过this作为参数传递给thread,因此开启线程后,运行的还是worker的run方法,而在run方法内部其实是调用的当前worker对象的firsttask对象)

下面我们来看看向ThreadPoolExecutor提交一个任务的时候的具体细节:

public void execute(Runnable command) {
        if (command == null)
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值