您当前的位置:网站首页>林冲,兰州天气预报-买下顶楼复式,完工轻奢大气,复式房屋

林冲,兰州天气预报-买下顶楼复式,完工轻奢大气,复式房屋

2019-05-16 08:49:17 投稿作者:admin 围观人数:264 评论人数:0次

布景

关于 Java 的线程池我想咱们必定不会生疏,在作业中或许自己平常的学习中多多少少都会用到,那你真的有了解过底层的完成原理吗?仍是说只逗留在用的阶段呢?而且关于 Java 线程池也是在面试中的一个高频的面试题,就像 HashMap 的完成原理相同,基本上面试必问,估量都现已被问烂大街了

题外话:HashMap 的完成原理真的现已被问烂了,在我本身的屡次面试中都不知道被问了几遍了,有的时分想想很古怪,为什么这个被问的烂大街的问题仍是会一向被问呢?可是从面试官的视点来想一下,假如一个被问的都烂大街的问题你都不好好预备对待,那怎么能好好的对待作业呢(个人鄙意)。

常用的几种线程池

咱们先来看下常用的几种线程池的创立办法,以及底层选用的完成原理

单个线程: Executors.newSingleThreadExecutor();

public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECOND林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子S,
new LinkedBlockingQueue()));
}

缓存线程: Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}

固定线程Executors.newFixedThreadPool(2);


public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}

守时线程: Executors.newScheduledThreadPool(3);(父类中)

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveT山西永禄村ime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}

中心 ThreadPoolExecutor

经过上面的几个线程池的底层完成,咱们能够发现底层都是经过 ThreadPoolExecutor 类来完成的,仅仅参数不相同,那咱们就很有必要来看一下ThreadPoolExecutor 这个类了

public ThreadPoolExecutor(i碧玺的成效与效果n艾泽拉斯国家地理t corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
Rejec最浪漫的事tedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerExcepti冰河世纪on();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

经过 JDK 的源码咱们能够看到 ThreadPoolExecutor 在 Java 的 concurrent 包下面,而且有四个结构办法,下面顺次介绍下各个参数的意义:

•corePoolSize: 中心线程数的巨细

•maximumPoolSize: 线程池中答应的最大线程数

•keepAliveTime: 闲暇线程答应的最大的存活时刻

•unit: 存活时刻的单位

•workQueue: 堵塞使命行列

•threadFactory: 线程工厂用来创立线程

•handler: 回绝战略,针对当行列满了时新来使命的处理办法

经过上面参数的剖析,咱们能够知道,单个线程的线程池便是线程池中只要一个线林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子程担任使命,所以 corePoolSize 和 maximumPoolSize 的数值都是为 1;当这个线程呈现任何反常后,线程池会主动创立一个线程,始终保持线程池中有且只要一个存活的线程。而且其他线程池也仅仅参数的设置不相同罢了。 咱们还需求知道几个常见的线程池类和接口的联系,以及一些办法,如下图

ThreadPoolExecutor 承继 AbstractExecutorService;AbstractExecutorService 完成 ExecutorService林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子, ExecutorService 承继 Executor

源码剖析

依据源码能够发现整个线程池大致分为 3 个部分,1. 是创立 worker 线程,2. 添加使命到 workQueue; 3.worker cctv4在线直播线程履行具体使命

创立 worker 线程,现在咱们来看下中心的 execute(Runnable command) 办法,假如作业线程小于指定的中心线程数时会测验去创立新的线程,

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 (wo帽子rkerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}

再看下addWorker(Runnable firstTask, boolean core) 办法


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 {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
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;
}

添加使命到 workQueue,这个堵塞行列内部的办法


public boolean o林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子ffer(E e) {
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
if (count.get() == capacity)
return false;
int c = -1;
Node node = new Node(e);
f石安妮inal ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get()药 < capacity) {
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
}
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return c >= 0;
}

w主力校草美男团orker 线程履行具体使命,堵塞或许超时去获取行列中的使命,进行履行


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 ((runStateAtL红警2east(ctl.get(), STOP) ||
(Thr日本田园猫ead.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
tr肺炎支原体阳性y {
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);
}
}
private Runnable getTask() {
boolean timed千禧Out = 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 = allowCoreThreadTime林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子Out || 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 (Interrupmu2569tedException retry) {
ti林冲,兰州天气预报-买下顶楼复式,竣工轻奢大气,复式房子medOut = false;
}
}
}

在刚刚创立线程池的时分,内部线程的数量是 0,当首个使命进行添加的时分,会依据参数的装备进行线程的创立,并跟着使命数的添加,会逐步创立新的线程直到不能创立新的线程停止。不能创立新的线程后,会将来的使命存放到堵塞行列中,让闲暇的线程去处理。当没有闲暇线程而且行列满了时分就会选用回绝战省略丢掉或许其他战略来处理。 回绝战略主要有四种,不同的回绝战略有不同的运用场景,需求依据状况决议运用。

•CallerRunsPolicy : 调用线程处理使命

•AbortPolicy : 抛出反常

•DiscardPolicy :梧州天气预报 直接丢掉

•DiscardOldestPolicy : 丢掉行列中最老的使命,履行新使命

小结

线程池在作业中的运用必不可少,怎么高雅的运用线程池能很大程度的提高功能和功率。依据实践的使用场景,装备适宜的线程池参数能够很大的驭提高项目的功能,也能够充分利用服务器的功能。


the end
买下顶楼复式,完工轻奢大气,复式房屋