[英]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.