Conjunto de subprocesos escritos a mano en Java: primera generación (original)

Perfil personal

El autor es un estudiante de tercer año de Heyuan. Las siguientes notas son algunas experiencias superficiales del autor en el camino del autoaprendizaje. Si hay algún error, corríjame. En el futuro, continuaré mejorando las notas. para ayudar a más entusiastas de Java a comenzar.

Grupo de subprocesos manuscritos de Java (primera generación)

  • El grupo de subprocesos se usa a menudo, por lo que hoy, por capricho, escribir un grupo de subprocesos a mano tendrá muchas deficiencias, sea más tolerante. Debido a que esta es también la versión de primera generación, el seguimiento será más perfecto.

Grupo de subprocesos escritos a mano: definir parámetros

	private final AtomicInteger taskcount=new AtomicInteger(0);
    private final AtomicInteger threadNumber=new AtomicInteger(0);
    private volatile int corePoolSize; 
    private final Set<MyThreadPoolExecutor.MyWorker> workers; 
    private final BlockingQueue<Runnable> waitingQueue; 
    private final String THREADPOOL_NAME="MyThread-Pool-";
    private volatile boolean isRunning=true; 
    private volatile boolean STOPNOW=false; 
    private final ThreadFactory threadFactory; 

taskcount: el número de tareas a ejecutar
threadNumber: el número de subprocesos, comenzando desde 0 y aumentando sucesivamente.
corePoolSize: número de subprocesos principales
trabajadores: subprocesos de trabajo
waitQueue: cola de espera
THREADPOOL_NAME: nombre del subproceso
isRunning: si ejecutar
STOPNOW: si detener inmediatamente
threadFactory: fábrica de subprocesos

Grupo de subprocesos escritos a mano - constructor

    public MyThreadPoolExecutor(int corePoolSize, BlockingQueue<Runnable> waitingQueue,ThreadFactory threadFactory) {
    
    
        this.corePoolSize=corePoolSize;
        this.workers=new HashSet<>(corePoolSize);
        this.waitingQueue=waitingQueue;
        this.threadFactory=threadFactory;
        //线程预热
        for (int i = 0; i < corePoolSize; i++) {
    
    
            new MyWorker();
        }
    }
  • Este constructor funciona:
  • 1: Asigne un valor al parámetro.
  • 2: Calentamiento del hilo. El constructor de MyWorker se llama según el tamaño de corePoolSize . Podemos ver lo que hace el constructor MyWorker.
	final Thread thread; //为每个MyWorker

        MyWorker(){
    
    
            Thread td = threadFactory.newThread(this);
            td.setName(THREADPOOL_NAME+threadNumber.getAndIncrement());
            this.thread=td;
            this.thread.start();
            workers.add(this);
        }
  • El constructor MyWorker genera Thread para el objeto actual a través de la fábrica de hilos ;
  • Y establezca el nombre : MyThread-Pool-self-incrementing thread number;
  • Luego llame al método de inicio del hilo para iniciar el hilo;
  • Finalmente , se almacena en la colección Set de trabajadores , para que se pueda realizar la reutilización de subprocesos.

Grupo de subprocesos escritos a mano: constructor predeterminado

	public MyThreadPoolExecutor(){
    
    
        this(5,new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory());
    }
  • Asignación de inicializador por defecto :
  • tamaño de la piscina central: 5
  • waitingQueue: new ArrayBlockingQueue<>(10), una cola de bloqueo finita de longitud 10
  • fábrica de hilos:Ejecutores.defaultThreadFactory()

Grupo de subprocesos escritos a mano: método de ejecución

	public boolean execute(Runnable runnable)
    {
    
    
        return waitingQueue.offer(runnable);
    }
  • En esencia, es poner Runnable (tarea) en la cola de espera .

Grupo de subprocesos escritos a mano: tareas de procesamiento

	   @Override
        public void run() {
    
    
            //循环接收任务
                while (true)
                {
    
    
                    if((!isRunning&&waitingQueue.size()==0)||STOPNOW)
                    {
    
    
                        break;
                    }else {
    
    
                        Runnable runnable = waitingQueue.poll();
                        if(runnable!=null){
    
    
                            runnable.run();
                            System.out.println("task==>"+taskcount.incrementAndGet());
                        }
                    }
                }
        }
  • En esencia, es una tarea de recepción de bucle infinito, y las condiciones de salida son las siguientes:
  • 1: Salir con gracia. Cuando isRunning es falso y el tamaño de la cola de waitQueue es 0 (es decir, no hay ninguna tarea)
  • 2: Salida violenta. Cuando STOPNOW es verdadero, se llama al método shutdownNow
  • El bloque de declaraciones else continuará tomando tareas, cuando la tarea! = nulo, llama al método de ejecución para procesar la tarea

Grupo de subprocesos escritos a mano: cierra correctamente el grupo de subprocesos

	public void shutdown()
    {
    
    
        this.isRunning=false;
    }

Grupo de subprocesos escritos a mano: cerrar violentamente el grupo de subprocesos

	public void shutdownNow()
    {
    
    
        this.STOPNOW=true;
    }

Grupo de subprocesos escritos a mano: código fuente

Código fuente de la clase de grupo de subprocesos escrito a mano

package com.springframework.concurrent;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池类
 * @author 游政杰
 */
public class MyThreadPoolExecutor {
    
    

    private final AtomicInteger taskcount=new AtomicInteger(0);//执行任务次数
    private final AtomicInteger threadNumber=new AtomicInteger(0); //线程编号
    private volatile int corePoolSize; //核心线程数
    private final Set<MyThreadPoolExecutor.MyWorker> workers; //工作线程
    private final BlockingQueue<Runnable> waitingQueue; //等待队列
    private final String THREADPOOL_NAME="MyThread-Pool-";//线程名称
    private volatile boolean isRunning=true; //是否运行
    private volatile boolean STOPNOW=false; //是否立刻停止
    private final ThreadFactory threadFactory; //线程工厂

    public MyThreadPoolExecutor(){
    
    
        this(5,new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory());
    }

    public MyThreadPoolExecutor(int corePoolSize, BlockingQueue<Runnable> waitingQueue,ThreadFactory threadFactory) {
    
    
        this.corePoolSize=corePoolSize;
        this.workers=new HashSet<>(corePoolSize);
        this.waitingQueue=waitingQueue;
        this.threadFactory=threadFactory;
        //线程预热
        for (int i = 0; i < corePoolSize; i++) {
    
    
            new MyWorker();
        }
    }

    /**
     * MyWorker就是我们每一个线程对象
     */
    private final class MyWorker implements Runnable{
    
    

        final Thread thread; //为每个MyWorker

        MyWorker(){
    
    
            Thread td = threadFactory.newThread(this);
            td.setName(THREADPOOL_NAME+threadNumber.getAndIncrement());
            this.thread=td;
            this.thread.start();
            workers.add(this);
        }

        @Override
        public void run() {
    
    
            //循环接收任务
                while (true)
                {
    
    
                    //循环退出条件:
                    //1:当isRunning为false并且waitingQueue的队列大小为0(也就是无任务了),会优雅的退出。
                    //2:当STOPNOW为true,则说明调用了shutdownNow方法进行暴力退出。
                    if((!isRunning&&waitingQueue.size()==0)||STOPNOW)
                    {
    
    
                        break;
                    }else {
    
    
                        //不断取任务,当任务!=null时则调用run方法处理任务
                        Runnable runnable = waitingQueue.poll();
                        if(runnable!=null){
    
    
                            runnable.run();
                            System.out.println("task==>"+taskcount.incrementAndGet());
                        }
                    }
                }
        }
    }

    public boolean execute(Runnable runnable)
    {
    
    
        return waitingQueue.offer(runnable);
    }
    //优雅的关闭
    public void shutdown()
    {
    
    
        this.isRunning=false;
    }
    //暴力关闭
    public void shutdownNow()
    {
    
    
        this.STOPNOW=true;
    }
}

Prueba usando código de grupo de subprocesos escrito a mano

package com.springframework.test;

import com.springframework.concurrent.MyThreadPoolExecutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;

public class ThreadPoolTest {
    
    

  public static void main(String[] args) {
    
    

    
      MyThreadPoolExecutor myThreadPoolExecutor = new MyThreadPoolExecutor
              (5,new ArrayBlockingQueue<>(6), Executors.defaultThreadFactory());

      for(int i=0;i<10;i++){
    
    

          int finalI = i;
          myThreadPoolExecutor.execute(()->{
    
    
              System.out.println(Thread.currentThread().getName()+">>>>"+ finalI);
          });

      }

      myThreadPoolExecutor.shutdown();

//      myThreadPoolExecutor.shutdownNow();



  }
}

Pregunta: ¿Por qué a veces disminuyen las tareas ejecutadas por la ejecución del grupo de subprocesos personalizado?

  • Esto se debe a que la cola de espera está llena y no puede dejar la tarea, lo que provoca que la tarea se descarte, lo que equivale a la política de rechazo DiscardPolicy.
    • Las soluciones son:
    • 1: establezca el número máximo de subprocesos para expandir automáticamente el grupo de subprocesos.
    • 2: aumentar la capacidad de la cola de espera

Finalmente: debido a que esta es la versión de primera generación de mi grupo de subprocesos escritos a mano, básicamente implementa la función de reutilización del grupo de subprocesos. Sin embargo, todavía hay muchas imperfecciones. En el futuro, habrá varios artículos más mejorados para actualizar el actual. grupo de hilos escritos a mano.

En el seguimiento, continuaremos publicando publicaciones de blog sobre el marco Spring escrito a mano del autor, Tomcat escrito a mano y otros marcos. ! ! ! !

Supongo que te gusta

Origin blog.csdn.net/weixin_50071998/article/details/123583632
Recomendado
Clasificación