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.
Directorio de artículos
-
- Perfil personal
- Grupo de subprocesos manuscritos de Java (primera generación)
-
- Grupo de subprocesos escritos a mano: definir parámetros
- Grupo de subprocesos escritos a mano - constructor
- Grupo de subprocesos escritos a mano: método de ejecución
- Grupo de subprocesos escritos a mano: tareas de procesamiento
- Grupo de subprocesos escritos a mano: cierra correctamente el grupo de subprocesos
- Grupo de subprocesos escritos a mano: cerrar violentamente el grupo de subprocesos
- Grupo de subprocesos escritos a mano: código fuente
- Pregunta: ¿Por qué a veces disminuyen las tareas ejecutadas por la ejecución del grupo de subprocesos personalizado?
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. ! ! ! !