【发布时间】:2019-10-27 20:34:14
【问题描述】:
我正在阅读ThreadPoolExecutor.java的源码,下面是execute的方法:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
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个核心线程,设置最大池大小为4。
我可以理解代码if (workerCountOf(c) < corePoolSize) { addWorkder(..) },这意味着如果当前核心线程数小于核心轮询大小,只需创建一个新线程来处理可运行命令。
我无法理解的是,假设我们已经拨打了两次execute(runnable),而且他们每个人都需要很长时间才能完成,所以他们现在还在忙,现在我们正在拨打第三次电话。
代码会做什么?我认为代码转到if (isRunning(c) && workQueue.offer(command)) {,因此命令被添加到工作队列中。但是,我不明白这第三条命令将由哪个线程执行。根据代码else if (workerCountOf(recheck) == 0),我认为工人数应该是2,因为我们已经添加了两个工人。
所以我的问题是什么时候添加第三个工人?
--编辑--
我的测试代码:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(4)
);
threadPoolExecutor.execute(new Command("A"));
threadPoolExecutor.execute(new Command("B"));
threadPoolExecutor.execute(new Command("C"));
}
static class Command implements Runnable {
private String task;
Command(String task) {
this.task = task;
}
@Override
public void run() {
try {
Thread.sleep(1000 * 10);
System.out.println(new Date() + " - " + Thread.currentThread().getName() + " : " + task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
打印出来:
Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-1 : A
Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-2 : B
Thu Jun 13 17:44:40 CST 2019 - pool-1-thread-1 : C
使用测试代码,我希望核心工作人员保持忙碌 10 秒,所以当execute("C") 我想打“核心工作人员很忙,将添加第三个工作人员”的情况时,但似乎有没有第三个工人?抱歉,怎么了?
谢谢。
【问题讨论】:
-
“代码会做什么?”我觉得调试器比我们能解释得更好……
-
@AndrewTobilko 是的,我正在尝试
-
@AndrewTobilko 用调试器调试线程调度代码真的很困难。极端的海森堡效应。
-
只有在现有的两个工作人员仍然忙碌时才会添加第三个工作人员。否则其中一人将接手任务。
-
@Thilo 感谢您指出
Otherwise one of them will pick up the task。我想我可以理解核心工作线程有一个循环从工作队列中获取工作,因此workQueue.offer(command)将启动其中一个,他们将处理可运行的。但是,我仍然无法通过阅读代码了解何时/如何添加第三名工人。谢谢。
标签: java multithreading threadpoolexecutor