为什么缓存线程池会创建两个线程,为什么关闭它会改变这种情况?
Why does a cached thread pool create two threads, and why does shutting it down change that?
这是我的 java 代码。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
class ExceptionThread2 implements Runnable {
@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println("eh = " + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
}
class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread ");
Thread t = new Thread(r);
System.out.println("created " + t);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("eh = " + t.getUncaughtExceptionHandler());
return t;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
//exec.shutdown();
}
}
结果:
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
run() by Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-1,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@2870fdbb
caught java.lang.RuntimeException
当我取消注释 //exec.shutdown()
时,结果不同。只创建了一个线程。
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
run() by Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
caught java.lang.RuntimeException
为什么?
当你这样做时:
exec.execute(new ExceptionThread2());
工作线程已创建并执行您的任务。
但是异常完成,抛出异常后死亡。
在这种情况下,线程池会创建另一个 worker 来替换死掉的 worker,因此您会看到两条 created
消息,但只有一条 run()
消息
这是执行您的任务的runWorker
:
* 1. We may start out with an initial task, in which case we
* don't need to get the first one. Otherwise, as long as pool is
* running, we get tasks from getTask. If it returns null then the
* worker exits due to changed pool state or configuration
* parameters. Other exits result from exception throws in
* external code, in which case completedAbruptly holds, which
* usually leads processWorkerExit to replace this thread.
final void runWorker(Worker w)
- Other exits result from exception throws in
external code, in which case completedAbruptly holds, which
usually leads processWorkerExit to replace this thread
您的可运行程序使其线程崩溃。因此池将用一个新线程替换该线程(用于您可能提交的下一个任务)。
如果池已经被关闭,它不会那样做。
这是我的 java 代码。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
class ExceptionThread2 implements Runnable {
@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println("eh = " + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
}
class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread ");
Thread t = new Thread(r);
System.out.println("created " + t);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("eh = " + t.getUncaughtExceptionHandler());
return t;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
//exec.shutdown();
}
}
结果:
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
run() by Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-1,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@2870fdbb
caught java.lang.RuntimeException
当我取消注释 //exec.shutdown()
时,结果不同。只创建了一个线程。
com.concurrent.example.HandlerThreadFactory@7f31245a creating new Thread
created Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
run() by Thread[Thread-0,5,main]
eh = com.concurrent.example.MyUncaughtExceptionHandler@6d6f6e28
caught java.lang.RuntimeException
为什么?
当你这样做时:
exec.execute(new ExceptionThread2());
工作线程已创建并执行您的任务。
但是异常完成,抛出异常后死亡。
在这种情况下,线程池会创建另一个 worker 来替换死掉的 worker,因此您会看到两条 created
消息,但只有一条 run()
消息
这是执行您的任务的runWorker
:
* 1. We may start out with an initial task, in which case we
* don't need to get the first one. Otherwise, as long as pool is
* running, we get tasks from getTask. If it returns null then the
* worker exits due to changed pool state or configuration
* parameters. Other exits result from exception throws in
* external code, in which case completedAbruptly holds, which
* usually leads processWorkerExit to replace this thread.
final void runWorker(Worker w)
- Other exits result from exception throws in external code, in which case completedAbruptly holds, which usually leads processWorkerExit to replace this thread
您的可运行程序使其线程崩溃。因此池将用一个新线程替换该线程(用于您可能提交的下一个任务)。
如果池已经被关闭,它不会那样做。