首页 > 代码库 > JDK之线程池分析
JDK之线程池分析
线程池组成
一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
线程池种类
1、newSingleThreadExecutor
创建一个单线程的线程池,以无界队列方式运行。这个线程池只有一个线程在工作(如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。)此线程池能够保证所有任务的执行顺序按照任务的提交顺序执行,同一时段只有一个任务在运行。
此类型线程池特别适合于需要保证执行顺序的场合。
2、newFixedThreadPool
创建固定大小的线程池,以无界队列方式运行。线程池满且线程都为活动状态的时候如果有新任务提交进来,它们会等待直到有线程可用。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。显式调用shutdown将关闭线程池。
此类型线程池比较符合常用场合。
3、newCachedThreadPool
创建一个可缓存的线程池。必要的时候创建新线程来处理请求,也会重用线程池中已经处于可用状态的线程。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程;当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
此类型线程池特别适合于耗时短,不需要考虑同步的场合。
4、newScheduledThreadPool创建可定时运行(初始延时),运行频率(每隔多长时间运行,还是运行成功一次之后再隔多长时间再运行)的线程池。
此类型线程池适合定时以及周期性执行任务的场合。
线程池的jdk实现corePoolSize的作用
在生成的线程池ThreadPoolExecutor中,有一个corePoolSize属性,它的作用是用来判断是否要创建新的线程,如果当前线程池中线程的数量大于corePoolSize,则有空闲线程则使用,没有空闲线程则创建线程。如果小于corePoolSize则不管怎样,都会从新创建线程。
/** * Core pool size, updated only while holding mainLock, but * volatile to allow concurrent readability even during updates. */ private volatile int corePoolSize;
执行线程池的execute方法时,不同的线程池种类不同的响应
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } }
工作线程Worker
工作线程执行它的run方法后,会一直试图去等待队列里面取出任务
/** * Main run loop */ public void run() { try { hasRun = true; Runnable task = firstTask; firstTask = null; while (task != null || (task = getTask()) != null) { //注意getTask()方法,它会循环着去取出来任务 runTask(task); task = null; } } finally { workerDone(this); } }
看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 } } }
JDK之线程池分析