Dos formas de implementar un grupo de subprocesos en Java

01 Escenarios de aplicación del grupo de subprocesos

(1) Solicitud

Por ejemplo, el software de retoque actual en la colección. Una imagen de 1920 x 1080 tiene más de 2 millones de píxeles, y se requieren muchos cálculos para procesar cada píxel de la imagen completa.

(2) lado del servidor

Cuando el lado del servidor procesa grandes datos y una gran cantidad de solicitudes, si solo es realizado por un solo hilo, no puede satisfacer la demanda.

Además, independientemente de si está procesando aplicaciones o servidores, incluso si se usan múltiples hilos, si los hilos se crean y destruyen con frecuencia, el tiempo final de creación y destrucción puede ser mayor que el tiempo real de ejecución. Reutilizar objetos es una buena opción, por lo que puede elegir un grupo de subprocesos.

Las clases Java comúnmente utilizadas involucradas en el grupo de subprocesos incluyen ThreadPoolExecutor, Executors, etc.

02 ThreadPoolExecutor

(1) ThreadPoolExecutor es más complicado para crear objetos. La siguiente figura muestra varios constructores proporcionados en JDK 11.

Estos parámetros implican principalmente la configuración de algunos parámetros clave del grupo de subprocesos. Tome el constructor con más parámetros como ejemplo:

public ThreadPoolExecutor(int corePoolSize, 
													int maximumPoolSize, 
													long keepAliveTime, 
													TimeUnit unit, 
													BlockingQueue<Runnable> workQueue, 
													ThreadFactory threadFactory, 
													RejectedExecutionHandler handler) {
	...
}
复制代码

corePoolSize El número de subprocesos guardados en el grupo de subprocesos cuando está inactivo.

maximumPoolSize El número máximo de subprocesos permitidos en el grupo de subprocesos.

keepAliveTime Cuando hay subprocesos inactivos y el número de subprocesos existentes es mayor que corePoolSize, el subproceso se elimina después del tiempo especificado y el subproceso no se elimina dentro del tiempo especificado.

unit Se refiere a la unidad de tiempo establecida de keepAliveTime.

workQueue Se usa para guardar la cola de tareas antes de la ejecución.

threadFactory Especifica la clase de fábrica para crear hilos personalizados.

handler El propósito de RejectedExecutionHandler es implementar algún procesamiento cuando las tareas se agregan después de que se cierra el grupo de subprocesos, como registrar la información del subproceso rechazado.

(2) métodos execute () y submit ()

Ambos pueden enviar tareas como un grupo de subprocesos, pero los detalles serán diferentes.

execute()Puede agregar una tarea, pero el tipo solo puede ser Ejecutable y la tarea no puede devolver resultados. Cuando se encuentra una excepción de subproceso automático, la información de excepción se imprime directamente y el subproceso principal no puede capturar la información de excepción.

submit()Puede agregar una tarea, pero devolver un objeto Future, y puede obtener el resultado devuelto a través de Future. Cuando se encuentra una excepción, la información de la excepción se puede capturar en el hilo principal.

Los parámetros del método submit () involucran dos tipos de interfaces invocables y Runnable, y sus principales diferencias son:

(A) El método call () de la interfaz invocable puede tener un valor de retorno, mientras que el método run () de la interfaz Runnable no tiene ningún valor de retorno.

(B) El método call () de la interfaz invocable puede generar una excepción de por vida, pero el método run () de la interfaz Runnable no puede declarar que se produce una excepción.

(3) Otros métodos comunes

shutdown() El subproceso principal finaliza inmediatamente y no se bloquea. Los subprocesos en el conjunto de subprocesos que se han ejecutado continuarán ejecutándose. No se agregarán nuevas tareas al conjunto de subprocesos. El conjunto de subprocesos continuará ejecutándose hasta que todos los subprocesos hayan completado la ejecución.

Cuando el subproceso programará inmediatamente el estado de APAGADO, en este momento ya no desea agregar Tarea al grupo de subprocesos, de lo contrario, arroje la excepción RejectedExecutionException.

shutdownNow()Interrumpir todas las tareas y lanzar InterruptException. Inmediatamente después de la ejecución, ingresa al estado STOP e intenta detener todos los subprocesos en ejecución, ya no procesa tareas que aún esperan en el grupo de subprocesos.

Después de ejecutar este método, devolverá las tareas no ejecutadas: Lista

isShutdown() Determine si el grupo de subprocesos se ha cerrado.

isTerminating() Devuelve verdadero si está en proceso de finalización.

isTerminated() Juzgue que todas las tareas se han completado.

awaitTermination() Compruebe si el grupo de subprocesos ha terminado el trabajo dentro del tiempo especificado.

03 ejecutores

Executors es una clase de creación de grupo de subprocesos que puede facilitar la creación de grupos de subprocesos a través de los métodos ya proporcionados.

(1) Métodos comunes proporcionados por los ejecutores:

newCachedThreadPool() Cree un grupo de subprocesos ilimitado que pueda reciclar subprocesos automáticamente. El denominado "grupo de subprocesos máximo" es el número máximo teórico de subprocesos almacenados en el grupo y el valor máximo de Integer.MAX_VALUE.

newCachedThreadPool(ThreadFactory) Subprocesos en un grupo de subprocesos personalizado

newFixedThreadPool(int) Crear un grupo de hilos acotado

newFixedThreadPool(int, ThreadFactory) Cree un grupo de subprocesos limitado de subprocesos personalizados.

newSingleThreadExector() Cree un grupo de subprocesos único para implementar tareas en una cola.

newSingleThreadExecutor() Cree un grupo de subprocesos único con una fábrica.

04 caso

(1) Use ThreadPoolExecutor para crear un grupo de subprocesos

package com.page.concurrent.pool;

import java.util.concurrent.*;

public class Game {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        		1, 2, 1000 * 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>());

        Future<String> future = threadPoolExecutor.submit(() -> {
            System.out.println("Should work 4 seconds.");
            Thread.sleep(1000 * 4);
            System.out.println("Work done.");
            return "OK";
        });

        String result = future.get();
        System.out.println("Thread response result is " + result);
        threadPoolExecutor.shutdownNow();
        System.out.println("Thread pool status: isShutdown=" + threadPoolExecutor.isShutdown());
        Thread.sleep(1000 * 5);
        System.out.println("Thread pool status: isTerminated" + threadPoolExecutor.isTerminated());
    }
}

复制代码

(2) Use Executors para crear un grupo de subprocesos

package com.page.concurrent.pool;

import java.util.concurrent.*;

public class Game {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<String> future = executorService.submit(() -> {
            System.out.println("Should work 4 seconds.");
            Thread.sleep(1000 * 4);
            System.out.println("Work done.");
            return "OK";
        });

        String result = future.get();
        System.out.println("Thread response result is " + result);
        executorService.shutdownNow();
        System.out.println("Thread pool status: isShutdown=" + executorService.isShutdown());
        Thread.sleep(1000 * 5);
        System.out.println("Thread pool status: isTerminated" + executorService.isTerminated());
    }
}

复制代码

Supongo que te gusta

Origin juejin.im/post/5e9830c4518825738c3648c9
Recomendado
Clasificación