我需要在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的实现)将创建一个缓存的线程池,最多只有一个,如果没有作业,它还会过期并死掉?
答案 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
最后一个终止后没有活动线程。