8

我是新手ExecutorService,想知道为什么以下代码正确打印“10 15”,即使我只创建了一个线程来处理超时?为什么我可以多次调用 schedule 而不会在单个线程执行程序上取消以前的任务?

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class TestExecutorService implements Runnable {
    public static ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor();
    private int delay;


    public TestExecutorService(int delay) {
        this.delay = delay;
    }

    public void run () {
        System.out.println(delay);
    }

    public static void main (String[] args) {
        SERVICE.schedule(new TestExecutorService(10), 10, TimeUnit.SECONDS);
        SERVICE.schedule(new TestExecutorService(15), 15, TimeUnit.SECONDS);

        SERVICE.shutdown();
    }
}
4

2 回答 2

13

Javadocs

任务保证按顺序执行,并且在任何给定时间不会有超过一个任务处于活动状态。

“处理超时”和“任务执行”的区别是答案的关键。您假设“单线程”意味着“一次只处理一个超时”,但它实际上意味着“一次只执行一个任务”。所有的超时都是同时处理的,但是如果在一个任务停止执行之前达到一个超时,它必须等待另一个超时才能执行。

于 2012-12-18T07:03:46.333 回答
10

在这种情况下,阅读Javadoc会很有帮助。它确实解释了虽然执行器将使用单个线程创建,但它将使用无界队列进行操作。这意味着您可以向执行程序提交多个任务,它们将排队等待一个接一个地运行,直到队列的最大边界(在本例中为无穷大)或直到 JVM 耗尽资源。

创建一个使用单个工作线程在无界队列上运行的 Executor。(但请注意,如果该单线程在关闭前的执行过程中因故障而终止,如果需要执行后续任务,则新线程将取代它。)任务保证按顺序执行,并且不会有超过一个任务处于活动状态在任何给定时间。与其他等效的 newFixedThreadPool(1) 不同,返回的执行程序保证不可重新配置以使用额外的线程。

在您的示例中,您的两个任务排队,并依次运行,这就是您获得(预期)输出的原因。

于 2012-12-18T06:59:08.600 回答