Почему кэшированный пул потоков создает два потока, и почему его закрытие изменяет это? - PullRequest
0 голосов
/ 27 мая 2018

Это мой код 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

Почему?

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Ваш работоспособный сбой потока.Таким образом, пул заменит этот поток новым (для следующей задачи, которую вы можете отправить).

Если пул уже закрыт, он этого не сделает.

0 голосов
/ 27 мая 2018

Когда вы делаете:

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)
  • Другие выходы являются результатом исключений во внешнем коде, и в этом случае завершается, и выполняется внезапно, что обычно приводит к processWorkerExit для замены этого потока
...