为什么执行程序在线程以异常结束时没有用完可用线程?

时间:2018-03-03 18:04:26

标签: java multithreading threadpool executorservice threadpoolexecutor

在以下方案中,我的任务会抛出异常。我不同意,在一次请求之后,我的池将无法处理任何进一步的请求,但它没有发生。线程池在这种情况下的行为如何?如何从池线程到主应用程序线程发生异常通信?

public class CallableClass implements Callable<String> {

    @Override
    public String call() throws Exception {
        throw new RuntimeException();
    }

}

class Test {
      ExecutorService executor = Executors.newFixedThreadPool(1);

      public void execute(){  
         try {
            System.out.println(executor);
            Future<String> future = executor.submit(new Task());
            System.out.println(executor);

            future.get();
        }catch(Exception e) {
           System.out.println(executor);
           e.printStackTrace();
        }
     }

  }

1 个答案:

答案 0 :(得分:1)

您可以通过打印当前正在执行的线程的名称来检查它:

@Override
public String call() throws Exception {
    System.out.println(Thread.currentThread().getName());
    ...
}
  
      
  1. 线程池在这种情况下的行为如何?
  2.   

工作人员通知执行程序服务它在工作时发生的异常。但是没有理由从ThreadPoolExecutor#workers集中移除该工作者。如果有需要,它将继续工作。

您不应该看到执行程序服务的任何失败。如果发生错误,它会用有效的工作者(或线程)替换无效的工作者(或线程):

  

如果任何线程因关闭前执行期间的故障而终止,则在需要执行后续任务时,新的线程将取代它。

     

ExecutorService.newFixedThreadPool(int) [JDK 9]

  
      
  1. 如何从池线程到主应用程序线程发生异常通信?
  2.   

Callable#call引发的任何异常都被ExecutionException包裹并弹出到调用方:

  

@throws ExecutionException如果计算引发异常

     

Future.get() [JDK 9]

支持ExecutionException#getCauseRuntimeException实例的一个示例:

} catch (ExecutionException e) { 
    Throwable cause = e.getCause();
    if (cause != null && cause instanceof RuntimeException) {
        System.out.println("A RuntimeException was thrown.");
    }
}