使用Java中的Executors进行串行调度队列?

时间:2017-04-03 17:31:09

标签: java multithreading executorservice threadpoolexecutor

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

理想情况下,每个引擎都有一个可以在0到1个线程之间进行扩展的线程池,这使得ExecutorService既可以是串行的,也不会在数百个线程中占用大量资源,但只有少数人看到活动。

然而,当我尝试使用

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

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

我发现当提交第二个作业时(如果第一个作业仍在运行)抛出一个RejectedExecutionException,我假设因为我有一个线程来运行两个作业,而执行者没有那样的。

我可以使用自己的队列来实现它,并根据需要启动/停止/处置我自己的Thread实例,但这似乎是0<=n<=1执行程序可以执行的操作。

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

1 个答案:

答案 0 :(得分:1)

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

  

同步队列没有任何内部容量,甚至没有容量。

因此,如果您用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

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