两个线程池死锁

 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(),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。都停止运行。

你可能感兴趣的:(两个线程池死锁)