【问题标题】:Why does a cached thread pool create two threads, and why does shutting it down change that?为什么缓存线程池会创建两个线程,为什么关闭它会改变呢?
【发布时间】:2018-11-06 05:09:04
【问题描述】:

这是我的 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

为什么?

【问题讨论】:

  • 主要区别是这个方法执行了两次,方法是'newThread()'。

标签: java threadpool executorservice threadpoolexecutor


【解决方案1】:

当你这样做时:

exec.execute(new ExceptionThread2());

创建一个工作线程并执行您的任务。

但它异常完成并在抛出异常后死亡。

在这种情况下,线程池创建另一个工作线程来替换死掉的工作线程,因此您会看到两条 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)
  • 其他退出由异常引发 外部代码,在这种情况下 completedAbruptly 成立,其中 通常会导致 processWorkerExit 替换此线程

【讨论】:

    【解决方案2】:

    您的 runnable 使其线程崩溃。因此池将用一个新线程替换该线程(用于您可能提交的下一个任务)。

    如果池已被关闭,则不会这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      相关资源
      最近更新 更多