Explicación detallada del principio subyacente del conjunto de subprocesos simultáneos de Java y el análisis del código fuente

1. Grupo de subprocesos y comparación de rendimiento de subprocesos

En el caso de un solo subproceso, la velocidad de procesamiento de las tareas mejora considerablemente en comparación con el rendimiento del uso del grupo de subprocesos. El grupo de subprocesos se puede reutilizar en el interior. Después de que el subproceso procesa la tarea, puede volver al grupo de subprocesos para procesar otras tareas. lo que reduce en gran medida la destrucción de subprocesos y el tiempo de creación.

Varios grupos de subprocesos que vienen con java:

ExecutorService executorService = Executors.newCachedThreadPool(); 
ExecutorService executorService1 = Executors.newFixedThreadPool(100); 
ExecutorService executorService2 = Executors.newSingleThreadExecutor(); 
ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

Todos los parámetros de construcción del grupo de subprocesos anterior se crean con ThreadPoolExecutor, pero los parámetros utilizados son diferentes.

El método de construcción utilizado por newCachedThreadPool: parámetros correspondientes (número de subprocesos principales, número máximo de subprocesos, tiempo de supervivencia del subproceso, unidad de tiempo de supervivencia del subproceso, cola), newCachedThreadPool tiene solo 0 subprocesos principales y el número de subprocesos temporales puede ser infinito, por lo que su eficiencia de ejecución es muy alta, SynchronousQueue es un modelo típico de productor consumidor, lo que equivale a una empresa de subcontratación.

nuevo ThreadPoolExecutor(0, Integer.MAX_VALUE, 
                              60L, TimeUnit.SECONDS, 
                              new SynchronousQueue<Runnable>())
El método de construcción utilizado por newCachedThreadPool: la cantidad de subprocesos principales y la cantidad de subprocesos temporales se personalizan.La cola LinkedBlockingQueue es una cola de bloqueo ilimitada, lo que equivale a esperar el procesamiento de tareas indefinidamente, pero la eficiencia es muy baja. Equivalente a una empresa estatal. 
nuevo ThreadPoolExecutor(nThreads, nThreads, 
                              0L, TimeUnit. MILISEGUNDOS, 
                              nueva LinkedBlockingQueue<Runnable>())
El método de construcción utilizado por newSingleThreadExecutor: la cantidad de subprocesos principales y la cantidad de subprocesos temporales son 1, lo que equivale a una persona que maneja innumerables tareas. La eficiencia es muy rápida cuando las tareas se pueden procesar rápidamente, pero será lento cuando las tareas necesitan ser procesadas Parece muy ineficiente. Es equivalente a una empresa privada, y todo lo hace una sola persona. 
nuevo FinalizableDelegatedExecutorService 
    (nuevo ThreadPoolExecutor(1, 1, 
                            0L, TimeUnit. MILLISECONDS, 
                            nuevo LinkedBlockingQueue<Runnable>()))

El grupo de subprocesos con mayor probabilidad de tener OOM: newCachedThreadPool, que no es una cola ilimitada, informará OOM cuando alcance el valor máximo de memoria

Las especificaciones de Ali no recomiendan los tres casos anteriores, pero los tres anteriores se pueden usar en empresas que no pueden alcanzar el valor máximo de la memoria.Ali recomienda un grupo de subprocesos personalizado ThreadPoolExecutor

 1.1 Comparación de grupos de subprocesos en la práctica

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDemo {

    public static void main(String[] args) {

        //定义3个线程池
        ExecutorService executorService = Executors.newCachedThreadPool();//很快
        ExecutorService executorService1 = Executors.newFixedThreadPool(100);//不快不慢
        ExecutorService executorService2 = Executors.newSingleThreadExecutor();//最慢

        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            executorService2.submit(new Task());
        }
        executorService.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }
}

1.2 Combate del ejecutor de ThreadPool

/**
 * 第31个任务会拒绝任务
 */
public class ThreadDemo {

    public static void main(String[] args) {

        //定义ThreadPoolExecutor
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10));
        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            threadPoolExecutor.submit(new Task());
        }
        threadPoolExecutor.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

1.3  Pregunta de la entrevista 1: Parámetros de grupo de subprocesos personalizados

público ThreadPoolExecutor(int corePoolSize, 
                          int maximumPoolSize, 
                          long keepAliveTime, 
                          unidad TimeUnit, 
                          BlockingQueue<Runnable> workQueue, 
                          ThreadFactory threadFactory, 
                          RejectedExecutionHandler handler) {
   
   

corePoolSize: número de subprocesos principales

int maximumPoolSize: el número máximo de subprocesos

long keepAliveTime: tiempo de supervivencia temporal del subproceso

Unidad TimeUnit: unidad de supervivencia de hilo temporal

BlockingQueue<Runnable> workQueue: cola de tareas

ThreadFactory threadFactory: clase de fábrica personalizada general

Manejador RejectedExecutionHandler: estrategia de rechazo, hay 4 definiciones, generalmente podemos personalizar la estrategia de rechazo

AbortPolicy: RejectedExecutionException se lanza por defecto para rechazar la tarea 
DiscardPolicy: Abandonar la tarea 
DiscardOldestPolicy: Lanzar la tarea más antigua a través de la estructura de la cola 
CallerRunsPolicy: El subproceso que llama al método de ejecución ejecuta la tarea

1.4  Esquema de ejecución del análisis del código fuente del conjunto de subprocesos de la pregunta de la entrevista (TODO) 

1.5 La diferencia entre los métodos de envío () y ejecución en las preguntas de la entrevista (TODO)

La diferencia entre enviar y ejecutar: hay un concepto de prioridad de envío y prioridad de ejecución en el hilo, y la prioridad de envío es más alta que la prioridad de ejecución. 
1. El método de ejecución está en el método de envío. 
2. El método de envío devolverá una función genérica futura, pero ejecutar no devolverá

 

 

1.6 La diferencia entre ofrecer() y agregar() en las preguntas de la entrevista

Tanto agregar como ofrecer son métodos para agregar tareas a la cola de tareas. La diferencia es que el método agregar no arroja una excepción, mientras que la oferta arrojará una excepción de interrupción. Esta es la única diferencia entre ellos.

 

 

1.7 nuevo grupo de subprocesos programados (POR HACER)

1.7.1 nuevo Combate de grupo de subprocesos programados (POR HACER)

1.7.2 Análisis de código fuente (TODO)

1.8 Política de denegación personalizada

Hay dos formas de personalizar la política de rechazo:

//Estrategia de rechazo personalizada 
RejectedExecutionHandler addedExecutionHandler = new RejectedExecutionHandler() { 
    @Override 
    public void addedExecution(Runnable r, ThreadPoolExecutor executor) { 
        System.out.println("Estrategia de rechazo personalizada, se puede almacenar en la base de datos"); } 
    } 
;

El segundo método: implemente la interfaz RejectedExecutionHandler y reescriba el método addedExecution.

import java.util.concurrent.*;

/**
 * 第31个任务会拒绝任务
 */
public class ThreadDemo {

    public static void main(String[] args) {

        //自定义拒绝策略
        RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("自定义拒绝策略,可以存入数据库");
            }
        };

        //定义ThreadPoolExecutor
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10),rejectedExecutionHandler);
        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            threadPoolExecutor.submit(new Task());
        }
        threadPoolExecutor.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_21575929/article/details/124939077
Recomendado
Clasificación