Resumen de métodos de implementación de subprocesos múltiples

Existen principalmente cuatro formas de implementar subprocesos múltiples JAVA:
heredar la clase Thread,
implementar la interfaz Runnable,
Callable y Future implementar subprocesos múltiples con resultados devueltos.
Usar ExecutorService

1. Heredar la clase Thread

La única forma de iniciar un hilo es a través del método de instancia start() de la clase Thread.
El método start() es un método nativo que inicia un nuevo hilo y ejecuta el método run().

/**
 * @author Myli
 * @create 2023-02-19 5:51
 */
public class testmyli {
    
    
    public static void main(String[] args) {
    
    
        MyThread myThread1 = new MyThread();
        myThread1.start();
    }
}

class MyThread extends Thread {
    
    
    public void run() {
    
    
        System.out.println("MyThread.run()");
    }
}

Thread es esencialmente una instancia que implementa la interfaz Runnable.
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

2. Implementar la interfaz Runnable

Como todos sabemos, Java es de herencia única. Si una clase ya tiene una clase principal, no puede extender Thread directamente. En este momento, si desea implementar subprocesos múltiples, puede implementar una interfaz Runnable.

/**
 * @author Myli
 * @create 2023-02-21 0:27
 */
public class testrunable {
    
    
    public static void main(String[] args) {
    
    
    //new一个MyThread,
        MyThread myThread = new MyThread();
       //new一个Thread
        Thread thread = new Thread(myThread);
        thread.start();
    }
    
    static class MyThread extends OtherClass implements Runnable {
    
    
        public void run() {
    
    
            System.out.println("MyThread.run()");
        }
    }
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

3. Implementar la interfaz invocable

/**
 * @author Myli
 * @create 2023-02-21 0:44
 */
public class testcallable {
    
    
    public static void main(String[] args) {
    
    

        //调用callable 可以有返回值 可以捕获异常
        Callable<String> tc = new TestCallable();

        FutureTask<String> task = new FutureTask<String>(tc);

        new Thread(task).start();
        try {
    
    
            System.out.println(task.get());//获取返回值
        } catch (InterruptedException | ExecutionException e) {
    
    
            e.printStackTrace();
        }
    }

     static class TestCallable implements Callable<String> {
    
    
        @Override
        public String call() throws Exception {
    
    
            System.out.println("实现callable:" + Thread.currentThread().getName());
            return "callable返回";
        }
    }

}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

4. Grupo de subprocesos

Los comunes son el
grupo de subprocesos de longitud fija (FixedThreadPool),
el grupo de subprocesos programados (ScheduledThreadPool),
el grupo de subprocesos almacenables en caché (CachedThreadPool),
el grupo de subprocesos de un solo subproceso (SingleThreadExecutor)
y completamente manual (ThreadPoolExecutor)

Grupo de subprocesos de longitud fija (FixedThreadPool)

// 1. 创建定长线程池对象 & 设置线程池线程数量固定为3
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
    
    
  public void run() {
    
    
     System.out.println("执行任务啦");
  }
};
// 3. 向线程池提交任务
fixedThreadPool.execute(task);

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Grupo de subprocesos programados (ScheduledThreadPool)

inserte la descripción de la imagen aquí

Grupo de subprocesos almacenables en caché (CachedThreadPool)

inserte la descripción de la imagen aquí

Grupo de subprocesos de un solo subproceso (SingleThreadExecutor)

inserte la descripción de la imagen aquí

(Ejecutor de grupo de subprocesos)

Aunque los cuatro grupos de subprocesos funcionales de Ejecutores son convenientes, no se recomienda su uso ahora. En su lugar, se recomienda usar ThreadPoolExecutor directamente. Esta forma de manejo hace que los estudiantes de escritura tengan más claras las reglas de ejecución del grupo de subprocesos y evita el riesgo de agotamiento de los recursos.

De hecho, los cuatro subprocesos funcionales de Executors tienen las siguientes desventajas:

FixedThreadPool y SingleThreadExecutor: el problema principal es que todas las colas de procesamiento de solicitudes acumuladas usan LinkedBlockingQueue, lo que
puede consumir mucha memoria o incluso OOM.
CachedThreadPool y ScheduledThreadPool: el principal problema es que el número máximo de subprocesos es Integer.MAX_VALUE, lo que
puede crear una gran cantidad de subprocesos, o incluso OOM.

// 创建线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,
                                             MAXIMUM_POOL_SIZE,
                                             KEEP_ALIVE,
                                             TimeUnit.SECONDS,
                                             sPoolWorkQueue,
                                             sThreadFactory);
// 向线程池提交任务
threadPool.execute(new Runnable() {
    
    
    @Override
    public void run() {
    
    
        ... // 线程执行的任务
    }
});
// 关闭线程池
threadPool.shutdown(); // 设置线程池的状态为SHUTDOWN,然后中断所有没有正在执行任务的线程
threadPool.shutdownNow(); // 设置线程池的状态为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表

inserte la descripción de la imagen aquí
Cuando la cantidad de subprocesos en el grupo de subprocesos alcanza la cantidad máxima de subprocesos, se debe implementar una política de rechazo. La estrategia de rechazo debe implementar la interfaz RejectedExecutionHandler e implementar el método addedExecution(Runnable r, ThreadPoolExecutor executor). Sin embargo, el marco Executors ha implementado 4 estrategias de rechazo para nosotros:

AbortPolicy (predeterminado): cancela la tarea y genera una excepción RejectedExecutionException.
CallerRunsPolicy: la tarea es manejada por el subproceso de llamada.
DiscardPolicy: descarta tareas, pero no genera excepciones. Este modo se puede utilizar para el procesamiento personalizado.
DiscardOldestPolicy: descarta la tarea sin procesar más antigua de la cola y luego intenta ejecutar la tarea nuevamente.

Tenga en cuenta la diferencia entre una cola acotada y una cola sin acotar: si usa una cola acotada, la estrategia de rechazo se ejecutará cuando la cola se sature y exceda el número máximo de subprocesos; y si usa una cola sin acotar, porque la cola de tareas siempre puede agregar tareas, establecer el tamaño máximo de grupo sin sentido.

Crear comparación de hilos

1. Las ventajas de implementar la interfaz Runnable o Callable sobre la herencia de la clase Thread

(1) La interfaz Runnable o Callable es adecuada para múltiples subprocesos para compartir recursos

(2) Herencia única en java, pero implementaciones de múltiples interfaces para mejorar la escalabilidad

(3) Aumentar la robustez del programa, el código y la independencia de datos

(4) El grupo de subprocesos solo se puede colocar en la clase de implementación de la interfaz Runable o Callable, y no se puede colocar directamente en la clase que hereda Thread

Diferencia entre invocable y ejecutable

(1) Callable reescribe el método call() y Runnable reescribe el método run()

(2) El método call() puede tener un valor de retorno después de la ejecución, pero el método run() no tiene valor de retorno

(3) El método call() puede lanzar una excepción, pero el método run() no puede

(4) Ejecute la tarea Callable para obtener un objeto Future, que representa el resultado del cálculo asíncrono. A través del objeto Future, puede comprender la ejecución de la tarea, cancelar la ejecución de la tarea y obtener el resultado de la ejecución.

referencia

Vínculo: subprocesos múltiples de Java: comprenda a fondo el grupo de subprocesos
Vínculo: tres formas de crear subprocesos y sus diferencias
Algunas referencias ya no pueden encontrar la fuente original

Supongo que te gusta

Origin blog.csdn.net/m0_54765221/article/details/129107166
Recomendado
Clasificación