Estoy recibiendo esta excepción en mi servidor tomcat (+liferay)

java.util.concurrent.RejectedExecutionException

mi clase es como que :

public class SingleExecutor extends ThreadPoolExecutor {
  public SingleExecutor(){
    super(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
  }

  @Override
  public void execute(Runnable command) {
    if(command instanceof AccessLogInsert){
        AccessLogInsert ali = (AccessLogInsert)command;
        ali.setConn(conn);
        ali.setPs(ps);
    }
    super.execute(command);
  }
}

Puedo obtener esta excepción en la línea super.execute(command);
Este error puede producirse cuando la cola está llena, pero el LinkedBlockingQueue tamaño es de 2^31, y estoy seguro de que no hay tantos espera de órdenes.

Al inicio todo es estable, pero después de volver a implementar una guerra comienza ocurren. Esta clase no es parte de la guerra, pero en un frasco en tomcat/lib.

¿Tiene usted alguna idea de por qué ha pasado y cómo solucionarlo ?

InformationsquelleAutor jpprade | 2011-11-18

2 Comentarios

  1. 71

    De ThreadPoolExecutor JavaDoc

    Nuevas tareas presentadas en el método execute(java.lang.Runnable) será rechazada cuando el Executor se ha cerrado, y también cuando el Executor utiliza finito de los límites para ambos máximo de subprocesos y la cola de trabajo de capacidad, y está saturado. En cualquier caso, el método execute invoca el RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) método de su RejectedExecutionHandler. Cuatro predefinidos controlador de las políticas que se proporcionan:

    1. En el valor predeterminado ThreadPoolExecutor.AbortPolicy, el controlador de lanza de un tiempo de ejecución RejectedExecutionException al rechazo.
    2. En ThreadPoolExecutor.CallerRunsPolicy, el hilo que invoca a ejecutar en sí se ejecuta la tarea. Esto proporciona un simple mecanismo de control de retroalimentación que se ralentizará el ritmo que las nuevas tareas que se han presentado.
    3. En ThreadPoolExecutor.DiscardPolicy, una tarea que no puede ser ejecutado es simplemente dejó.
    4. En ThreadPoolExecutor.DiscardOldestPolicy, si el ejecutor no se cierra, la tarea a la cabeza de la cola de trabajo se ha caído, y, a continuación, la ejecución se vuelve a intentar (que puede fallar de nuevo, haciendo que este se repita.)

    Es posible definir y utilizar otros tipos de RejectedExecutionHandler clases. Para ello se requiere un poco de cuidado, especialmente cuando las políticas están diseñadas para funcionar sólo en virtud de la particular capacidad o las colas de las políticas.

    Presumiblemente, por lo tanto, la recarga de la guerra desencadena un cierre de Executor. Prueba a poner la pertinente bibliotecas en la guerra, para que Tomcat ClassLoader tiene una mejor oportunidad de correctamente la recarga de su aplicación.

    • Última parte de la respuesta es buena.
    • «Nuevas tareas presentadas en el método execute(java.lang.Runnable) será rechazada cuando el Ejecutor se ha cerrado.» Esto dio lugar a un error en mi código, que lo resuelto por dormir el hilo de 500ms después del cierre (que puede no ser necesario), luego ajuste el programador para null, de modo que la próxima vez que una tarea debe ejecutarse, el método en cuestión, se comprueba si el programador es null. Si es así, se crea uno nuevo. Así, el rechazo de la razón del cierre es eliminado.
    • dormir no es necesario, pero adecuado control de concurrencia es. Además, mientras que su «solución» puede dejar de accidentes, es simplemente ocultar lo que suena como un gran problema de la propiedad de los recursos.
  2. 6

    Sólo para añadir a OrangeDog excelente respuesta, el contrato de un Executor es, de hecho, de tal forma que su execute método arrojará RejectedExecutionException cuando el ejecutor es saturado (es decir, no hay espacio en la cola).

    Sin embargo, habría sido más útil si se bloqueado lugar, automáticamente, a la espera hasta que haya espacio en la cola para la nueva tarea.

    Con el siguiente personalizado BlockingQueue es posible lograr que:

    public final class ThreadPoolQueue extends ArrayBlockingQueue<Runnable> {
    
        public ThreadPoolQueue(int capacity) {
            super(capacity);
        }
    
        @Override
        public boolean offer(Runnable e) {
            try {
                put(e);
            } catch (InterruptedException e1) {
                return false;
            }
            return true;
        }
    
    }

    Que, básicamente, se implementa el algoritmo de contrapresión, la disminución del productor cuando el ejecutor se satura.

    Utilizar como:

    int n = Runtime.getRuntime().availableProcessors();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(0, n, 1, TimeUnit.MINUTES, new ThreadPoolQueue(n));
    for (Runnable task : tasks) {
        executor.execute(task); //will never throw, nor will queue more than n tasks
    }
    executor.shutdown();
    executor.awaitTermination(1, TimeUnit.HOURS);
    • CallerRunsPolicy ya existe con el fin de lograr esto, y ofrece un mejor rendimiento que el simple bloqueo.

Dejar respuesta

Please enter your comment!
Please enter your name here