public static void scheduleCreateRequest() {
createRequestExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"start");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"end");
}
});
System.out.println("submit finished");
}
public static void main (String[] args) throws InterruptedException {
createRequestExecutor=new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>(),new ThreadPoolExecutor.DiscardOldestPolicy());
createRequestScheduled= Executors.newScheduledThreadPool(1);
createRequestScheduled.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(new Date());
scheduleCreateRequest();
}
}, 0, 1, TimeUnit.SECONDS);
System.out.println("finished");
}
以上代码会造成“死锁”
条件1
createRequestExecutor 中只有一个线程,并且使用了同步队列SynchronousQueue,拒绝策略DiscardOldestPolicy
此时当有线程在执行时,createRequestScheduled第二次提交时,拒绝策略直接生效
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
会继续执行,依然拒绝,继续重复execute,直到StackOverflow。
条件2
createRequestScheduled捕获到StackOverflowError后,不再增加下一次的task。
if (ScheduledFutureTask.super.runAndReset()) {//Error返回false
setNextRunTime();
reExecutePeriodic(outerTask);
}
但createRequestScheduled的线程池会继续从队列中take数据,此时由于队列为空,会await。但是已经没有线程再add。就会一直wait下去。
而createRequestExecutor在执行完第一次后,也因为没有schedule调度而一直wait。都停止运行。
网友评论