我正在创建具有10个线程的固定大小的线程池,如下所示:
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < poolSize; ++i) {
executorService.execute(factory.get());
}
现在,在生成10个线程之后,它们中的每一个都正在运行一个可运行的线程。这里的runnable由factory.get()提供
现在,我想做一个事情,一旦线程关闭,即它已经完成了一项任务,它将再次选择另一个可运行的对象并开始运行它。因此,基本上检查所有10个线程的状态,如果线程关闭,则再次执行可运行的命令。
我知道我可以做类似的事情,在其中我可以如下调用executorService shutdown()方法:
while (!executorService.isShutdown()) {
try {
executorService.execute(factory.get());
} catch (RejectedExecutionException e) {
if (!executorService.isShutdown())
log.warn("task submission rejected");
}
}
但是在这种方法中,问题在于我一直在调用execute函数,这会增加LinkedBlockingQueue并不能达到我的目的。
如果我能以某种方式检查Threads状态,那将是一件好事,因为那样的话,它将避免回头从executor服务中获取更多工作的开销。
请提出如何在代码中做到这一点。
答案 0 :(得分:1)
您可以使用有界的执行器。以下是code
的Brian Goetz撰写的jcip/**
* BoundedExecutor
* <p/>
* Using a Semaphore to throttle task submission
*
* @author Brian Goetz and Tim Peierls
*/
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
}
}
}
然后只需创建并使用它即可:
ExecutorService executorService = Executors.newFixedThreadPool(10);
BoundedExecutor boundedExecutor = new BoundedExecutor(executorService,10);
while (!executorService.isShutdown()) {
try {
boundedExecutor.submitTask(factory.get());
} catch (InterruptedException e) {
}
}
这样,您将始终有10个线程在运行,新任务仅在旧任务完成后才提交,并且您可以通过关闭执行程序来停止执行。
答案 1 :(得分:0)
如果要连续运行10个线程,为什么要使用线程池?只需自己启动10个线程即可。
为什么在10个工作线程的顶部有一个“控制器”线程?只需让每个线程要求执行下一个任务即可。
以下内容假设factory.get()
是线程安全的。
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (;;) {
Runnable r = factory.get(); // <-- must be thread-safe
if (r == null)
break; // stop thread if no more tasks to execute
try {
r.run();
} catch (Exception e) {
// log exception here
}
}
}).start();
}
如果需要,将10个线程对象保存在一个数组中。
如果您希望能够在不使factory.get()
返回null的情况下关闭线程,请添加一个易失性布尔值,并在循环中进行检查。