终止Java线程

时间:2013-10-14 16:52:58

标签: java multithreading

我可以看到很多次被问到这个问题。再次问这个道歉。我有一个奇怪的问题。

我有一份工作,通过ExecutorService提交数千个作业作为单独的Runnable任务。这是在一个简单的for循环中完成的。循环结束时,我调用service.shutdown(),然后调用awaitTermination。

由于要提交的线程数量巨大,因此线程会一直挂起,直到所有任务都提交完毕。

有没有办法,这些线程可以在执行完成后立即终止?

2 个答案:

答案 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个线程)是没有用的,因为它实际上并没有让你获得更多的并发性。只需将执行程序限制为合理数量的线程,“挂起”类型的问题可能会消失。