合理的使用线程池有三个好处:
1.降低资源消耗。
2.提高响应速度。
3.提高线程的可管理性。
先看流程图:
如果当前线程池中的线程数目小于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); } } }