我从执行程序服务创建固定线程池。但是如果有一些运行时异常或错误(OutOfMemory Error)出现,那么线程将会死亡,并且线程数量会持续减少,并且一次线程数将为零,这就是所谓的无声线程查杀。保持固定线程数始终为
一种方法是捕捉throwable(这不是一个好习惯),以避免线程kill。有什么办法可以永远保持固定的线程数?如果线程杀死/死亡,那么一个新的线程应该自动产生,这样我们总是有固定数量的线程。
任何建议是可观的。
我从执行程序服务创建固定线程池。但是如果有一些运行时异常或错误(OutOfMemory Error)出现,那么线程将会死亡,并且线程数量会持续减少,并且一次线程数将为零,这就是所谓的无声线程查杀。保持固定线程数始终为
一种方法是捕捉throwable(这不是一个好习惯),以避免线程kill。有什么办法可以永远保持固定的线程数?如果线程杀死/死亡,那么一个新的线程应该自动产生,这样我们总是有固定数量的线程。
任何建议是可观的。
SingleThreadExecutor
的ApiDoc声明如下:“但请注意,如果这个单线程在关闭之前的执行期间由于失败而终止,那么如果需要执行后续任务,则新的线程将取代它。
这似乎也适用于带有多个线程的ThreadPools(请参阅下面的演示程序)。因此,除非程序运行真正的OutOfMemoryError
(例如,不是偶然会分配太大的字节数组),否则将不会发生无声的线程杀死。如果程序运行到一个真正的OutOfMemoryError
那么我认为可以做很多事情:由于内存不足,必须执行的所有类型的语句(在最后的块中)可能突然无法执行,并且可能使程序处于不一致的状态(如不带线程的ThreadPool)。
下面的演示程序显示了所有任务的执行和THEAD,名称显示新的线程由线程池创建:
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class SilentKillThread {
public static void main(String[] args) {
try {
new SilentKillThread().runTest();
} catch (Exception e) {
e.printStackTrace();
}
}
static int MAX_TASKS = 3;
static long SLEEP_TIME_MS = 400;
AtomicInteger tasksDoneCount = new AtomicInteger();
public void runTest() throws Exception {
ThreadPoolExecutor tp = new ThreadPoolExecutor(MAX_TASKS, MAX_TASKS,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < MAX_TASKS; i++) {
tp.execute(new FailingTask());
}
for (int i = 0; i < MAX_TASKS; i++) {
tp.execute(new SleepingTask());
}
tp.shutdown();
if (tp.awaitTermination(SLEEP_TIME_MS * 4, TimeUnit.MILLISECONDS)) {
System.out.println("Finished");
} else {
System.out.println("Finished but threadpool still active.");
}
System.out.println("Tasks done: " + tasksDoneCount.get());
}
class FailingTask implements Runnable {
@Override
public void run() {
String tname = Thread.currentThread().getName();
System.out.println(tname + " Sleeping");
try { Thread.sleep(SLEEP_TIME_MS); } catch (Exception e) { e.printStackTrace();}
int tcount = tasksDoneCount.incrementAndGet();
System.out.println(tname + " Done sleeping " + tcount);
throw new OutOfMemoryError();
}
}
class SleepingTask implements Runnable {
@Override
public void run() {
String tname = Thread.currentThread().getName();
System.out.println(tname + " Sleeping");
try { Thread.sleep(SLEEP_TIME_MS); } catch (Exception e) { e.printStackTrace();}
int tcount = tasksDoneCount.incrementAndGet();
System.out.println(tname + " Done sleeping " + tcount);
}
}
}
你能提供一个沉默线程的例子杀人?我无法复制它。我更新了[这个答案](http://stackoverflow.com/a/24697277/3080094)中的代码,在第一个'Runnable'的末尾抛出了一个'OutOfMemoryError',但程序仍然运行正常 - ThreadPoolExecutor只是丢弃旧的线程并创建一个新线程。 – vanOekel
@vanOekel您确定ThreadPool执行程序在旧线程死亡时创建新线程。我从未在任何地方找到过。任何链接都会非常有帮助。 – Naveen
那么更新的代码显示它发生了。所以让我们来回顾一下:当池中的某个线程不再可用时,您能否显示ThreadPoolExecutor不会启动新线程,或者提供解释何时发生的文档链接? – vanOekel