提交和等待执行人服务终止的正确方法



我正在学习如何使用 ExecutorService 在 Java 中使用线程池,这是我正在处理的一个例子:

public class Example {
    static class WorkerThread implements Runnable {
        private String command;
        public WorkerThread(String s) {
            this.command = s;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
            processCommand();
            System.out.println(Thread.currentThread().getName() + " End.");
        }
        private void processCommand() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        @Override
        public String toString() {
            return this.command;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.execute(worker);
        }
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.SECONDS);
//        while (!executor.isTerminated()) {
//        }
        System.out.println("Finished all threads");
    }
}

我有两个问题:

  1. 我应该如何等待ExecutorService终止,我应该使用awaitTermination()还是isTerminated()(有人建议后者是一种错误的方式(?

  2. Runnable是否正确添加到执行器,还是应该submit()Future<T>回调一起使用?

这可能取决于上下文,所以请您解释一下(对于这两个问题(我何时应该使用提到的每个解决方案。

这个程序不是在等待线程终止,JVM正在等待: 我得到的输出是:

pool-1-thread-1 Start. Command = 0
pool-1-thread-2 Start. Command = 1
pool-1-thread-3 Start. Command = 2
pool-1-thread-4 Start. Command = 3
pool-1-thread-5 Start. Command = 4
Finished all threads
pool-1-thread-2 End.
pool-1-thread-1 End.
pool-1-thread-4 End.
pool-1-thread-1 Start. Command = 5
pool-1-thread-3 End.
pool-1-thread-2 Start. Command = 7
pool-1-thread-5 End.
pool-1-thread-4 Start. Command = 6
pool-1-thread-5 Start. Command = 9
pool-1-thread-3 Start. Command = 8
pool-1-thread-3 End.
pool-1-thread-5 End.
pool-1-thread-4 End.
pool-1-thread-1 End.
pool-1-thread-2 End.

您会注意到Finished all threads不在底部。如果要等待所有线程完成,请使用以下命令:

public class Example {
    static class WorkerThread implements Runnable {
        private String command;
        public WorkerThread(String s) {
            this.command = s;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
            processCommand();
            System.out.println(Thread.currentThread().getName() + " End.");
        }
        private void processCommand() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        @Override
        public String toString() {
            return this.command;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
        for (int i = 0; i < 10; i++) {
            tasks.add(Executors.callable(new WorkerThread("" + i)));
        }
        executor.invokeAll(tasks);
        System.out.println("Finished all threads");
        // this merely terminates the ExecutorService, otherwise the JVM will never close.
        executor.shutdown();
        executor.awaitTermination(10L, TimeUnit.SECONDS);
    }
}

您会注意到正确的输出:

pool-1-thread-1 Start. Command = 0
pool-1-thread-5 Start. Command = 4
pool-1-thread-4 Start. Command = 3
pool-1-thread-3 Start. Command = 2
pool-1-thread-2 Start. Command = 1
pool-1-thread-3 End.
pool-1-thread-1 End.
pool-1-thread-5 End.
pool-1-thread-3 Start. Command = 5
pool-1-thread-2 End.
pool-1-thread-4 End.
pool-1-thread-2 Start. Command = 8
pool-1-thread-1 Start. Command = 7
pool-1-thread-5 Start. Command = 6
pool-1-thread-4 Start. Command = 9
pool-1-thread-1 End.
pool-1-thread-4 End.
pool-1-thread-3 End.
pool-1-thread-5 End.
pool-1-thread-2 End.
Finished all threads

实现它的几种方法:(a( 在while (!executor.isTerminated())内呼叫awaitTermination(long someTime, TimeUnit ....)。(b( 将所有可调用对象存储在集合对象中并调用executor.invokeAll(....)。这将等到执行程序服务完成所有任务。

1.我应该如何等待执行服务终止,我应该使用 awaitTermination(( 还是 isTerminated(((有人建议后者是错误的方式(?

  1. 您可以在shutdown()后使用awaitTermination()
  2. 您可以通过传递可运行/可调用任务列表在执行器服务上使用invokeAll()
  3. 您可以使用CountDownLatch

有关更多详细信息,请查看相关的 SE 问题:

如何使用执行器服务等待所有线程完成?

执行器服务,如何等待所有任务完成

等待所有线程完成,然后再关闭执行程序

2.Runnables是否正确添加到执行器中,或者我应该将submit((与未来回调一起使用?

  1. 如果只想运行命令而不等待结果,请使用 Runnable
  2. 如果要在执行后检查任务的结果,请使用Callable

如果你使用 submit() ,异常隐藏在框架中,你必须注意正确处理异常。

查看相关的 SE 问题:

在 ExecutorService 的提交和 ExecutorService 的执行之间进行选择

executor.submit 和 executor.execute 在 Java 中的这段代码中的区别?

相关内容

  • 没有找到相关文章

最新更新