ExecutorService关闭方法的行为为何不同?

问题描述

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ArrayBlockingQUeueExampe {

    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<>(2);

        Runnable r = () -> {
            int i = 0;
            while (true) {
                try {
                    System.out.println("Added : "+i);
                    q.put(i++);
                    TimeUnit.MILLISECONDS.sleep(1000);
                } catch (InterruptedException e) {
                    e.printstacktrace();
                }
            }
        };

        Runnable r2 = () -> {
            while (true) {
                try {
                    Integer take = q.take();
                    System.out.println("Taken : "+take);
                } catch (InterruptedException e) {
                    e.printstacktrace();
                }
            }
        };

        ExecutorService  service = Executors.newFixedThreadPool(2);
        service.submit(r);
        service.submit(r2);
        service.shutdown();
    }
}

我要在结束代码调用shutdown(),因此执行程序服务必须立即关闭,不应执行以前提交的任务,但是当我运行此代码时,它为什么一直在运行?

解决方法

javadocs for shutdown()表示已启动“有序”关机:

…执行先前提交的任务,但不接受新任务。

因此,您的无限任务正在执行,并且不会接受任何新任务(无论如何您都不会提供任何新任务)。

相反,shutdownNow() says

尝试停止所有正在执行的任务,暂停正在等待的任务的处理,并返回正在等待执行的任务的列表。 此方法不等待主动执行的任务终止。使用awaitTermination来做到这一点。

,

shutdown()用于正常关闭,这意味着它将仅在所有提交的任务完成之前退出。 shutdownNow()将中断当前所有正在执行的任务并关闭。但是,我在您的代码中注意到,您正在捕获InterruptedException而没有退出循环,因此您的程序将在中断后继续运行。

如果要立即终止,则需要更改两个位置:

  1. 使用shutdownNow
  2. 捕获InterruptedException时跳出循环