注:JDK1.8版本
线程池7个构造参数
线程池构造方法:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) |
1.corePoolSize 线程核心线程数(线程池中保留的线程数,即使它们是空闲的,默认情况下不会回收,除非设置allowCoreThreadTimeOut为true)
allowCoreThreadTimeOut设置true时,会中断所有核心线程
interruptIdleWorkers(boolean) : void - java.util.concurrent.ThreadPoolExecutor interruptIdleWorkers() : void - java.util.concurrent.ThreadPoolExecutor allowCoreThreadTimeOut(boolean) : void - java.util.concurrent.ThreadPoolExecutor |
2.maximumPoolSize 线程池中允许的最大线程数(maximumPoolSize = corePoolSize 不会有额外的创建线程,只有核心线程在工作)
3.keepAliveTime 线程空闲时间(线程数大于核心线程,剩余空闲线程最大等待时间)
4.unit 线程空闲时间单位
5.workQueue 线程池队列(线程池相关队列SynchronousQueue,LinkedBlockingQueue,DelayedWorkQueue )用于存放线程任务
SynchronousQueue :同步阻塞队列
分为两种模式,默认是非公平模式
公平模式:TransferQueue,队列任务先进先出
非公平模式:TransferStack,队列任务先进后出
队列任务添加满时,阻塞队列;队列任务消费为空时,阻塞队列
6.threadFactory 线程工厂用于创建线程
7.handler 拒绝策略
AbortPolicy:抛出java.util.concurrent.RejectedExecutionException异常
CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
DiscardOldestPolicy:丢弃任务队列中最旧任务
DiscardPolicy:丢弃当前将要加入队列的任务
线程池工作原理
1.execute 添加线程任务
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { //校验当前线程是否小于核心线程数 if (addWorker(command, true)) //添加工作任务 return; c = ctl.get(); } 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); } else if (!addWorker(command, false)) //队列添加满,创建非核心工作任务,创建失败后淘汰线程任务 reject(command); } |
2.addWorker 创建执行线程的worker
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); if (rs >= SHUTDOWN && //校验线程状态,队列是否为空 ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) // 校验当前工作线程数是否大于核心/最大线程数 return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); //创建工作任务 final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { // 校验线程状态 if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); // 添加工作任务,并更新最大线程池数量 if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { // 启动工作任务 t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; } |
3.t.start() 开启工作任务
t.start()->Worker.run()->Worker.runWoker()
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { //获取线程任务 w.lock(); if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); // 执行线程任务 } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); // 移除工作任务 } } |
4.getTask() 执行]线程任务
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { // 校验线程状态及队列是否为空 decrementWorkerCount(); return null; } int wc = workerCountOf(c); boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())){ // 校验线程是否>最大线程/空闲超时且任务数>1/队列为空 if (compareAndDecrementWorkerCount(c)) //cas减少任务数量 return null; continue; } try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take(); //获取队列线程任务 if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } } |
创建线程池4种情况
1.newCachedThreadPool 缓存线程池
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()) |
注:缓存线程池是一个无线扩容的线程池(核心线程为0,最大线程数不受限制),默认空闲时间60s,超过空闲时间时回收线程;线程没有回收前可重复利用
应用场景:流量洪峰且线程处理时间端(处理任务速度 > 提交任务速度,耗时少的任务)
2.newFixedThreadPool 固定线程池
注:固定大小线程池(核心线程=最大线程),没有空闲线程,默认情况核心线程不会回收,默认情况队列无上限,大量线程任务进入队列可能导致内粗溢出
应用场景:限流处理减少系统承受压力(受内存限制,量少且任务急增情况,建议用在访问外部系统)
3.newSingleThreadExecutor 单例线程池
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory));} |
注:单列线程池(核心线程=最大线程=1)只有一个线程执行任务,没有空闲线程,默认情况核心线程不会回收,默认情况队列无上限,大量线程任务进入队列可能导致内粗溢出
应用场景:执行任务有先后顺序(量少且无时效场景)
4.newScheduledThreadPool 周期性线程池
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); } |
注:周期性线程池(自定义核心线程,最大线程数量不限制);非核心线程执行完立马回收,默认情况队列无上限且有延迟效果
应用场景:定时任务