java线程池核心线程不被摧毁的原理及分析
目录
- 为什么要用线程池?
- 如何做到每个工作线程都可以被重复利用呢?
- 线程池是如何保持核心线程不被摧毁呢?
- 总结
为什么要用线程池?
- 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用
- 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因线程过多消耗内存,也避免了因线程过少,浪费系统资源
如何做到每个工作线程都可以被重复利用呢?
先看下线程池的工作原理:
原理如上图,线程池有七个核心参数
corePoolSize
线程池核心线程数maximumPoolSize
线程池最大线程数量keepAliveTime
空闲线程存活时间unit
空闲线程存活时间单位workQueue
工作队列threadFactory
线程工厂handler
拒绝策略
线程池之所以能做到重复利用,是因为线程池的核心线程不会被摧毁,执行完任务后会重复利用
线程池是如何保持核心线程不被摧毁呢?
首先看先线程池是如何处理任务的,如下图
下面我们看下核心部分源码:
- 当有一个任务添加进来时,线程池会创建一个Worker,Worker是实现Runphpnable方法的,所以Worker执行时会调用run方法,run方法会接着调用runWoker方法
- 主要看这一行代码,调用getTask方法获取任务并且执行 while (task != null || (task = getTask()) != null)
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTa编程sk; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { /www.devze.com/ 主要看这一行代码,调用getTask方法获取任务并且执行 while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; /编程客栈/ if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt 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); } }
- 看下getTask方法是如何实现的
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); // Are workers subject to culling? boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) 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; } } }
- 主要看这几行代码
- getTask方法通过调用任务队列的take方法,不断的获取线程
- 如果任务队列里面数量为0,则会一直阻塞,一直等到有任务加入,从而保证了核心线程不被摧毁
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论