我在ThreadPoolExecutor中运行任务时发现了一个意外的死锁。
这个想法是启动更改标志的辅助任务的主要任务。 主任务暂停,直到辅助任务更新标志。
我想知道:
corePoolSize = 2是一个安全值来防止这种死锁吗?
import java.util.concurrent.*;
class ExecutorDeadlock {
/*------ FIELDS -------------*/
boolean halted = true;
ExecutorService executor;
Runnable secondaryTask = new Runnable() {
public void run() {
System.out.println("secondaryTask started");
halted = false;
System.out.println("secondaryTask completed");
}
};
Runnable primaryTask = new Runnable() {
public void run() {
System.out.println("primaryTask started");
executor.execute(secondaryTask);
while (halted) {
try {
Thread.sleep(500);
}
catch (Throwable e) {
e.printStackTrace();
}
}
System.out.println("primaryTask completed");
}
};
/*-------- EXECUTE -----------*/
void execute(){
executor.execute(primaryTask);
}
/*-------- CTOR -----------*/
ExecutorDeadlock(int corePoolSize,BlockingQueue<Runnable> workQueue) {
this.executor = new ThreadPoolExecutor(corePoolSize, 4,0L, TimeUnit.MILLISECONDS, workQueue);
}
/*-------- TEST -----------*/
public static void main(String[] args) {
new ExecutorDeadlock(2,new LinkedBlockingQueue<>()).execute();
//new ExecutorDeadlock(1,new LinkedBlockingQueue<>()).execute();
//new ExecutorDeadlock(0,new SynchronousQueue<>()).execute();
}
}
答案 0 :(得分:6)
你如何期望这对线程数&lt; 2 if
起作用当池中有空闲执行程序时,执行程序服务从队列中获取任务。在你的情况下(&lt; 2)执行程序线程永远不会被第一个任务释放。 这里没有死锁问题。
修改强>
好的,我挖出了一些信息,这就是我发现的。首先来自ThreadPoolExecutor
任何BlockingQueue都可用于转移和保留提交的任务。 此队列的使用与池大小调整相互作用:
If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing. If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread. If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
好的,现在和queuess offer
方法一样
SyncQueue:
如果另一个线程是,则将指定的元素插入此队列 等着收到它。
的LinkedBlockingQueue
将指定的元素插入此队列,等待空间变为可用。
offer
方法的返回值确定新任务将在新线程中排队或运行。
由于LinkedBlockingQueue
将新任务排队,因为它可以存在容量,因此任务被排队并且不会产生新线程。但是SyncQueu
不会排队另一个任务,因为没有其他线程在等待某些事情被排队(offer
在任务未入队时返回false)这就是为什么会产生新的执行程序线程。
如果您阅读ThreadPoolExecutor
LinkedBlockingQueue
和SynchronousQueue
的javadoc并检查execute
方法的实施情况,您将得出相同的结论。
所以你错了,文档中有explenation:)