Exploración de problemas de manejo de excepciones de dos maneras: envío del ejecutor del grupo de subprocesos

Prefacio:

  Me pregunto si ha pensado si necesita detectar excepciones internas en un grupo de subprocesos ejecutado en modo ejecutor o sumbit.

Por ejemplo, suelo encontrar lo siguiente en mi código:

  1. En el grupo de subprocesos donde se ejecuta el envío, detecte todas las excepciones y luego el método de envío devuelve verdadero. Finalmente, se ejecuta el método get () del grupo de subprocesos para obtener la cantidad de resultados de ejecución exitosa y la cantidad de éxitos se devuelve al usuario (piense si este método es realmente inútil, no habrá excepciones y todos las ejecuciones de subprocesos serán exitosas. Este es un número falso de éxitos)

ArrayList<Future<Boolean>> futures = Lists.newArrayList();
for (Target target : targetList) {
    
    
    Future<Boolean> isSuccess = threadPoolExecutor.submit(() -> {
    
    
        // 每一个线程要做的事情
        try {
    
    
             dosomething(target);
        } catch (Exception e) {
    
    
            log.error(e.getMessage(), e);
        }
        //catch 住异常 且返回成功
        return true;
    });
    futures.add(isSuccess);
}
// 使用get去得到submit执行结果
long count = futures.stream().map(s -> {
    
    
    try {
    
    
        return s.get();
    } catch (Exception e) {
    
    
        log.error(e.getMessage(), e);
        return false;
    }
}).filter(s -> s).count();
//模拟返回给用户提示信息 想想这个笔数是否是一个假的笔数呢?是否都是成功的呢?
log.info("当前任务执行完成的笔数{}", count);

  2. En el grupo de subprocesos donde se ejecuta el envío, no detecte deliberadamente la excepción y finalmente obtenga el resultado de la ejecución ejecutando el método get ().

  Si alguna vez has visto este enfoque, te recomiendo que leas este artículo mío.

Conclusión primero

Conclusión uno:

  Si ocurre una excepción, el ejecutor iniciará un nuevo subproceso para su procesamiento (incluso si se excede el límite del grupo de subprocesos establecido por threadPoolExecutor)


// 1、线程池核心 最大线程数都限制为1个
// 2、线程池执行五次任务,其中一个任务抛出异常去中断该线程
// 3、探究剩余四次任务线程池执行逻辑

// 结论:线程池即使设置为只有1个容量,一个线程因为异常中断后,仍然会再开新的线程,去处理剩余任务

ThreadPoolExecutor pool = new ThreadPoolExecutor( 1, 1,
                                                 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

// 五个循环 
IntStream.rangeClosed(1, 5).forEach(i -> pool.execute(() -> {
    
    

    log.info("开始:" + Thread.currentThread().getName());
    if (i == 1) {
    
    
        throw new RuntimeException("异常抛出"); 
    }
    log.info("结束:执行第" + i + "次,"  + Thread.currentThread().getName());
}));

//执行结果 新开了 pool-1-thread-2去执行剩余4次任务
[pool-1-thread-1] INFO com.example.mytest.exceptionTest.futureExcutorException - 开始:pool-1-thread-1
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 开始:pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 结束:执行第2次,pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 开始:pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 结束:执行第3次,pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 开始:pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 结束:执行第4次,pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 开始:pool-1-thread-2
    [pool-1-thread-2] INFO com.example.mytest.exceptionTest.futureExcutorException - 结束:执行第5次,pool-1-thread-2

Conclusión dos:

   Si ocurre una excepción, enviar no informará un error (en la superficie, la excepción se ha tragado)

ThreadPoolExecutor pool = new ThreadPoolExecutor( 1, 1,
                                                 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
//提交任务执行
List<Future<Boolean>> tasks = IntStream.rangeClosed(1, 4).mapToObj(i -> pool.submit(() -> {
    
    
    if (i == 2) {
    
    
        throw new RuntimeException("异常抛出");
    }
    return true;
})).collect(Collectors.toList());

// 执行结果 异常不会报错
...

Una breve exploración de las razones.

Pregunta 1: ¿En qué paso el ejecutor inicia un nuevo hilo para su procesamiento?
Insertar descripción de la imagen aquí

Pregunta 1: ¿Por qué enviar no informa un error (parece que se ha tragado la excepción)?
Insertar descripción de la imagen aquí

Resumir posibles problemas en el código.

   threadPoolExecutor.sumbit (con valor de retorno), detecta manualmente la excepción y devuelve true , que es un identificador sin sentido del número de éxitos, por lo que no puede utilizar este número de éxitos como lógica de ejecución empresarial posterior ni como datos precisos devueltos al usuario. .

Supongo que te gusta

Origin blog.csdn.net/qq_44716086/article/details/129203238
Recomendado
Clasificación