转载

Java多线程_线程池

合理的使用线程池有三个好处:

1.降低资源消耗。

2.提高响应速度。

3.提高线程的可管理性。

线程池的实现原理

先看流程图:

Java多线程_线程池

如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;如果当前线程池中的线程数>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若任务缓存队列已满,则会尝试创建新的线程去执行这个任务;如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理。

看一下excute的源码:

public void execute(Runnable command) {
        if (command == null) // 空任务抛出异常
            throw new NullPointerException();
        int c = ctl.get();
        // 1. 如果工作线程数小于核心线程数,则添加新的线程
        if (workerCountOf(c) < corePoolSize) { 
            if (addWorker(command, true))
                return; // 添加成功则返回
            c = ctl.get(); // 否则获取线程池状态
        }
        // 2.  工作线程数大于等于核心线程数,则将任务放入缓存任务队列
        // 与操作: 如果线程池正在运行,而且成功将任务插入缓存任务队列两个条件
        // 都满足则进入条件语句内
        if (isRunning(c) && workQueue.offer(command)) { // 第一次检查
            int recheck = ctl.get();
            // 如果不处于运行状态,则将任务从任务缓存队列移除
            if (! isRunning(recheck) && remove(command)) // 第二次检查
                reject(command); // 拒绝任务
            else if (workerCountOf(recheck) == 0) // 第二次检查通过
                addWorker(null, false); // 添加无初始任务的线程
        }
        // 3. 任务入队失败,说明任务缓存任务队列已满,尝试添加新的线程处理
        // 如果添加失败则以某种方式拒绝任务
        else if (!addWorker(command, false))
            reject(command);
    }

线程池创建线程时,会将线程封装成工作线程Worker,Worker在执行完任务后,还会循环获取工作队列里的任务来执行。可以从Worker类的run()方法里看出这点:

public void run(){
    try{
        Runnable task = firstTask();
        firstTask() = null;
        while (task != null || (task = getTask()) != null){
            runTask(task);
            task = null ;
        }finally{
            workerDone(this);
        }
    }
}
原文  https://segmentfault.com/a/1190000020082597
正文到此结束
Loading...