ThreadPoolExecutor一些原理问题
2014-02-28 11:53
423 查看
今天被同事问到,ThreadPoolExecutor是怎么在线程执行后,保存线程的; worker线程去调用具体的业务线程,是不是就启动了两次线程。
平时用的比较多的是用ExecutorService 来创建newCachedThreadPool(), newFixedThreadPool(),
SingleThreadExecutor()等
看了一下源代码,这几个建线程池的方法都是创建ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize就是运行的核心线程的数,maximumPoolSize就是最大线程数,keepAliveTime是空闲线程的等待时间,workQueue是用来存放等待线程的。
当poolSize<corePoolSize时,每新来一个任务,则会创建一个工作线程(worker)来处理当前的任务, worker 处理完第一个线程后,会处理queue里的线程。worker在keepAliveTime的时间内,如果没有收到新的任务,则该worker会消失
1. ThreadPoolExecutor是怎么在线程执行后,一直保留worker线程(小于corePoolSize)存活的?
答案在getTask方法的代码里:
当前的线程数<corePoolSize时,workerCanExit()返回false,
无条件循环到 r = workQueue.take();
take是阻塞方法,因此work的线程会一直等待, 不会退出,等到queue里任务后再执行。
2. worker线程去调用具体的业务线程,是不是就启动了两次线程
注意: worker线程会去调用任务线程里的run方法。而不是start方法。从而避免了多次创建线程
平时用的比较多的是用ExecutorService 来创建newCachedThreadPool(), newFixedThreadPool(),
SingleThreadExecutor()等
看了一下源代码,这几个建线程池的方法都是创建ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize就是运行的核心线程的数,maximumPoolSize就是最大线程数,keepAliveTime是空闲线程的等待时间,workQueue是用来存放等待线程的。
当poolSize<corePoolSize时,每新来一个任务,则会创建一个工作线程(worker)来处理当前的任务, worker 处理完第一个线程后,会处理queue里的线程。worker在keepAliveTime的时间内,如果没有收到新的任务,则该worker会消失
1. ThreadPoolExecutor是怎么在线程执行后,一直保留worker线程(小于corePoolSize)存活的?
答案在getTask方法的代码里:
Runnable getTask() { for (;;) { try { int state = runState; if (state > SHUTDOWN) return null; Runnable r; if (state == SHUTDOWN) // Help drain queue r = workQueue.poll(); else if (poolSize > corePoolSize || allowCoreThreadTimeOut) r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS); else r = workQueue.take(); if (r != null) return r; if (workerCanExit()) { if (runState >= SHUTDOWN) // Wake up others interruptIdleWorkers(); return null; } // Else retry } catch (InterruptedException ie) { // On interruption, re-check runState } } }
当前的线程数<corePoolSize时,workerCanExit()返回false,
无条件循环到 r = workQueue.take();
take是阻塞方法,因此work的线程会一直等待, 不会退出,等到queue里任务后再执行。
2. worker线程去调用具体的业务线程,是不是就启动了两次线程
注意: worker线程会去调用任务线程里的run方法。而不是start方法。从而避免了多次创建线程
private void runTask(Runnable task) { final ReentrantLock runLock = this.runLock; runLock.lock(); try { /* * Ensure that unless pool is stopping, this thread * does not have its interrupt set. This requires a * double-check of state in case the interrupt was * cleared concurrently with a shutdownNow -- if so, * the interrupt is re-enabled. */ if (runState < STOP && Thread.interrupted() && runState >= STOP) thread.interrupt(); /* * Track execution state to ensure that afterExecute * is called only if task completed or threw * exception. Otherwise, the caught runtime exception * will have been thrown by afterExecute itself, in * which case we don't want to call it again. */ boolean ran = false; beforeExecute(thread, task); try { task.run(); ran = true; afterExecute(task, null); ++completedTasks; } catch (RuntimeException ex) { if (!ran) afterExecute(task, ex); throw ex; } } finally { runLock.unlock(); } }
相关文章推荐
- ThreadPoolExecutor的PriorityBlockingQueue支持问题
- 深入java线程池的使用详解
- java中通用的线程池实例代码
- 深入理解apahce的工作模式perfork、worker
- C#线程池用法详细介绍
- 关于线程池
- Apache Prefork、Worker和Event三种MPM分析
- 黑马程序员-Java基础加强之线程池
- JDK-线程池
- tomcat线程池设置
- Java 线程池的原理与实现
- 线程池
- 多线程执行完后主程序再执行(包括需要子线程返回结果)
- 交通灯管理系统
- 关于线程池结构以及互斥锁的运行机制
- glib库异步队列和线程池代码分析
- 黑马程序员 java Executors
- java.util包中的线程运用
- .Net线程问题解答