在 Java 中使用执行器的串行调度队列?

Serial dispatch queue using Executors in Java?

我需要管理 Java 中的大量串行调度队列。有许多引擎模块需要每个模块管理自己的 运行 循环(其中一些可能很快完成,另一些可能会阻塞很长时间)。提交给每个引擎的作业必须运行顺序。

理想情况下,每个引擎都有一个在 0 到 1 个线程之间缩放的线程池,使 ExecutorService 既串行,又不会在有数百个线程的情况下占用大量资源,但只有少数人看到activity.

但是,当我尝试使用 或者:

new ThreadPoolExecutor(0, 1, 30L, TimeUnit.SECONDS, new SynchronousQueue<>());

new ThreadPoolExecutor(1, 1, 30L, TimeUnit.SECONDS, new SynchronousQueue<>());

我发现当提交第二份工作时(如果第一份工作仍然是 运行ning)抛出 RejectedExecutionException,我假设因为我有一个线程到 运行两份工作,遗嘱执行人不喜欢这样。

我可以用我自己的队列和 start/stop/dispose 我自己的 Thread 按需实例来实现它,但这似乎是 0<=n<=1 执行器可以做的事情。

是否有 Executors. 方法(或 Executor 的实现)将创建一个缓存线程池,最多只有一个,如果没有作业,它也可以过期并死亡?

您的特定问题来自使用 SynchronousQueue,如文档所述:

A synchronous queue does not have any internal capacity, not even a capacity of one.

因此,如果您将其替换为 LinkedBlockingQueue,它确实有效。

但是,关于 Executors,您可以使用的是 Executors.newSingleThreadExecutor,因为它在顶部使用一个线程来执行任务。

一个简单的例子:

public static void main( String[] args )
{
    ExecutorService executor = Executors.newFixedThreadPool(1);
    TestThread t1 = new TestThread(1);
    TestThread t2 = new TestThread(2);
    executor.submit(t1);
    Future<?> f2 = executor.submit(t2);
    try {
        f2.get();
    } catch (InterruptedException | ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ThreadPoolExecutor tt = (ThreadPoolExecutor) executor;
    System.out.println(tt.getActiveCount()); //ensuring that there is no active threads in the pool after last thread terminates
}

public static class TestThread implements Runnable{
    private int id;

    public TestThread(int num){
        id = num;
    }
    public void run() {
        System.out.println("running thread: " + id);
        try {
            Thread.sleep(2000);
            System.out.println("After sleeping thread " + id);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

给出预期的输出:

running thread: 1
After sleeping thread 1
running thread: 2
After sleeping thread 2
0

最后一个线程终止后没有活动线程。