簡體   English   中英

終止Java線程

[英]Terminating a Java Thread

我可以看到這個問題被問了很多遍。 很抱歉再次提出這個問題。 我有一個奇怪的問題。

我有一個工作,它通過ExecutorService作為獨立的Runnable任務提交了數千個工作。 這是通過簡單的for循環完成的。 for循環的結尾,我調用service.shutdown(),然后調用awaitTermination。

由於要提交的線程數量巨大,因此線程會一直掛起,直到提交所有任務為止。

有什么辦法可以在執行完成后就優雅地終止這些線程?

您可以創建新的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) {
            }
        }
    }
}

正確的是, 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線程)是沒有用的,因為它實際上並沒有為您帶來更多的並發性。 只需將執行程序限制為合理數量的線程,“掛起”類型的問題可能就會消失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM