我可以看到很多次被问到这个问题。再次问这个道歉。我有一个奇怪的问题。
我有一份工作,通过ExecutorService提交数千个作业作为单独的Runnable任务。这是在一个简单的for循环中完成的。循环结束时,我调用service.shutdown(),然后调用awaitTermination。
由于要提交的线程数量巨大,因此线程会一直挂起,直到所有任务都提交完毕。
有没有办法,这些线程可以在执行完成后立即终止?
答案 0 :(得分:1)
您可以在不调用ThreadPoolExecutor
的情况下创建新的java.util.concurrent.Executors
:
int corePoolSize = 0;
int maximumPoolSize = 64;
int keepAliveTime = 5000;
ExecutorService executorService =
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
来自javadoc:“如果池当前有多个corePoolSize线程,如果多余的线程空闲时间超过keepAliveTime,那么它们将被终止”
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
修改强>
这是一个小例子,如果你在Eclipse调试环境中运行它,你应该看到线程来来往往:
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ExecutorTest {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(0, 64, 1000,
TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
for (int i = 0; i <= 500; i ++) {
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
}
executorService.submit(new TestTask());
}
}
public static class TestTask implements Runnable {
public void run() {
try {
Thread.sleep(new Random().nextInt(1500));
} catch (InterruptedException e) {
}
}
}
}
答案 1 :(得分:0)
shutdownNow()
允许您使用挂起任务中止执行是正确的。如果你的目标是做足够的工作来计算一些结果(这将花费不确定数量的任务),但是一旦你得到结果就停止做更多的工作,那么你需要一些方法来Runnable
对象发信号通知它应该停止循环。类似的东西:
ExecutorService svc = ...
AtomicBoolean done = new AtomicBoolean();
for (int i=0; i < jobs.length; i++) {
svc.submit(new MyRunnable(done, jobs[i]));
if (done.get()) break;
}
class MyRunnable implements Runnable {
private final Whatever job;
private final AtomicBoolean done;
MyRunnable (AtomicBoolean done, Whatever job) { this.done = done; this.job = job; }
public void run() {
if (done).get() return;
//do the work
if (somehowComputeThatTheWorkIsComplete) done.set(true);
}
}
如果由于启动太多线程而导致事情悬而未决,那么考虑使用Executors.newFixedThreadPool() - 计算机实际上不能同时执行比可用逻辑核心数更多的工作。因此,使用无界线程池(可以创建最多Integer.MAX_VALUE
个线程)是没有用的,因为它实际上并没有让你获得更多的并发性。只需将执行程序限制为合理数量的线程,“挂起”类型的问题可能会消失。