vas*_*ace 3 java multithreading executorservice java.util.concurrent
每个方法的注释public static ExecutorService newCachedThreadPool()中的Executor类:
Threads that have not been used for sixty seconds are terminated and
removed from the **cache**.
Run Code Online (Sandbox Code Playgroud)
我想知道缓存在哪里以及它是如何工作的?因为我Collection在ThreadPoolExecutor或者它的超类中没有看到任何可能的静态变量。
从技术上讲Worker, aRunnable包含对 a 的引用,Thread而不是 aThread本身。
让我们深入了解这门课的机制。
Executors.cachedThreadPool 使用这个构造函数来自 ThreadPoolExecutor
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
Run Code Online (Sandbox Code Playgroud)
其中 60s 对应于keepAliveTime时间。
ARunnableFuture是从提交的Callable或 中创建的Runnable。
这将传递给execute()方法。
该execute方法尝试将任务插入到workQueue,在我们的例子中是SynchronousQueue。由于 的语义,这将失败并返回 false SynchronousQueue。
(坚持这个想法,当我们谈论缓存方面时,我们会重新审视这个)
调用继续调用addIfUnderMaximumPoolSize方法,在execute该方法中将创建一个java.util.concurrent.ThreadPoolExecutor.Worker可运行对象并创建一个线程并将创建Worker的workers对象添加到hashSet。(其他人在答案中提到了)
然后它调用thread.start().
Worker 的 run 方法很重要,需要注意。
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
Run Code Online (Sandbox Code Playgroud)
此时您已经提交了一个任务,并且创建了一个线程并运行它。
在run方法中,如果您注意到有一个 while 循环。这是一段非常有趣的代码。
如果任务不为空,它将短路并且不检查第二个条件。
一旦任务运行使用runTask并且任务引用设置为空,调用就会进入第二个检查条件,它将它带入getTask方法。
这是决定工人是否应该被清除的部分。
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,工作队列会被轮询一分钟,以检查队列中是否有任何新任务。如果不是,它将返回 null 并检查 worker 是否可以退出。
返回 null 意味着我们将打破 while 并来到finally块。
这里从 HashSet 中删除了 worker,引用的 Thread 也消失了。
回到我们在任务提交中讨论的 SynchronousQueue。
在事件中,我提出一个任务,其中workerQueue.offer并workerQueue.poll能够协同工作,也就是说,为处理一个任务在那些60岁之间,我可以重新使用线程。
如果我在每个任务执行之间设置 59 秒 vs 61 秒的睡眠,这可以在实际中看到。
59 秒后,我可以看到线程被重新使用。61 秒后,我可以看到在池中创建了一个新线程。
注意实际时间可能因机器而异,我run()只是打印出来Thread.currentThread().getName()
如果我遗漏了什么或误解了代码,请在评论中告诉我。