es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Los ejecutores de Java no encolan alguna tarea.

No pude encontrar ningún ejecutor que cumpla con mis requisitos. Quiero tener un ExecutorService con un tamaño de núcleo (corePoolSize), un tamaño máximo (maximumPoolSize) y una BlockingQueue.

Cuando se llama a la función “execute”, como de costumbre, se utiliza un hilo principal (core thread). Si los hilos principales están ocupados, entonces se coloca la tarea en la cola y si la cola está llena, se crea un nuevo hilo hasta llegar al tamaño máximo del pool (maximumPoolSize). Este es el comportamiento estándar para ThreadPoolExecutor.
ThreadPoolExecutor

Todo está bien hasta esta parte. Puedo crear un ThreadPoolExecutor con estas especificaciones.

Pero para algunas tareas, no las encolo, sino que creo un nuevo hilo si el hilo principal está lleno. Pero si se alcanza el tamaño máximo del pool (maximumPoolSize), encolo la tarea, pero primero la coloco al frente de la cola.

¿Cómo puedo implementar este requisito? ¿Existe alguna funcionalidad incorporada que pueda utilizar?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para este requisito específico, la implementación estándar del ThreadPoolExecutor puede no ser suficiente. Sin embargo, es posible crear una implementación personalizada mediante la extensión de la clase ThreadPoolExecutor y la anulación del método execute() para especificar el comportamiento deseado.

    En primer lugar, los hilos principales pueden ser utilizados por defecto utilizando el método super.execute(). Si los hilos principales están en uso, la tarea puede ser colocada en la cola de bloqueo utilizando el método offer(). Si la cola está llena, se puede crear un nuevo hilo utilizando de nuevo el método super.execute().

    Para implementar la segunda parte del requisito, se puede utilizar un contador para realizar un seguimiento del número de hilos en ejecución. Cuando el contador es igual o superior a máximoTamañoDelPool, las tareas pueden ser colocadas en la cola utilizando el método put(). Si no, se puede crear un nuevo hilo utilizando el método super.execute().

    Aquí hay un ejemplo de implementación:

    public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
    
        private AtomicLong threadsCount = new AtomicLong(0);
        private int maxSize = Integer.MAX_VALUE;
        private BlockingQueue<runnable> customQueue;
    
        public CustomThreadPoolExecutor(int corePoolSize, int maxPoolSize, BlockingQueue<runnable> queue) {
            super(corePoolSize, maxPoolSize, 0L, TimeUnit.MILLISECONDS, queue);
            this.customQueue = queue;
            this.maxSize = maxPoolSize;
        }
    
        @Override
        public void execute(Runnable task) {
            if (threadsCount.get() < getCorePoolSize()) {
                super.execute(task);
                threadsCount.incrementAndGet();
            } else if (!customQueue.offer(task)) {
                if (threadsCount.get() < maxSize) {
                    super.execute(task);
                    threadsCount.incrementAndGet();
                } else {
                    try {
                        customQueue.put(task);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }
    
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            threadsCount.decrementAndGet();
        }
    }
    

    En esta implementación, una variable AtomicLong se utiliza para llevar un seguimiento del número de hilos en ejecución. También se especifica el número máximo de hilos. Si el número de hilos en ejecución es inferior al tamaño del grupo principal, la tarea se puede ejecutar utilizando el método super.execute(). De lo contrario, la tarea se ofrece a la cola de bloqueo. Si el método offer() devuelve false, se verifica el número de hilos en ejecución. Si es menor que el tamaño máximo del grupo, se crea un nuevo hilo utilizando el método super.execute(). Si se alcanza el tamaño máximo del grupo, la tarea se coloca en la cola utilizando el método put().

    El método afterExecute() se anula para disminuir la variable threadsCount cuando una tarea se completa.

    En general, esta implementación personalizada debería cumplir con los requisitos especificados en la pregunta.

Comments are closed.