一、 前言
很多时候,我们会执行多个任务,如果每次都是如此的创建线程 -> 执行任务 -> 销毁线程,会造成很大的性能开销。这时候需要池化技术的思想,通过预先创建好多个线程,放在池中,这样可以在需要使用线程的时候直接获取,避免多次重复创建、销毁带来的开销。
二、简单实现线程池原理
1、定义线程数,程序计数器CountDownLatch,创建线程池对象;
2、初始化线程数至WorkThread[]并启动,执行任务插入BlockingQueue队列里;
3、使用CountDownLatch线程计数器,计算任务执行数,目的是先执行完子任务,最后执行主线程任务;
4、最后关闭线程池,调用线程interrupt()中断线程,再清空线程计数器;
package com.chen.springboot01.utils;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author ccg
* @Date 2022/3/21 23:10
* @Version 1.0
*/
public class CustomThreadPoolExecutor implements Executor {
private Integer corePoolSize;
private BlockingQueue<Runnable> taskQueue;
private WorkThread[] workPool;
public CustomThreadPoolExecutor(Integer corePoolSize) {
this.corePoolSize = Optional.ofNullable(corePoolSize).map(v -> v > 5 ? 5 : v).orElse(5);
this.taskQueue = new ArrayBlockingQueue<>(this.corePoolSize * 10);
this.initWorkPool(this.corePoolSize);
}
@Override
public void execute(Runnable command) {
this.addWorkQueue(command);
}
private void initWorkPool(Integer size) {
this.workPool = new WorkThread[size];
for (int i = 0; i < size; i++) {
this.workPool[i] = new WorkThread();
this.workPool[i].start();
}
}
private void addWorkQueue(Runnable command) {
try {
// 非阻塞,默认三秒超时
this.taskQueue.put(command);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void shutdown() {
for (int i = 0; i < workPool.length; i++) {
workPool[i].cancel();
workPool[i] = null;
}
System.out.println("shutdown thread pool");
}
private class WorkThread extends Thread {
private volatile boolean flag = true;
@Override
public void run() {
try {
//判断是否可以取任务
while (this.flag && !isInterrupted()) {
Runnable task = taskQueue.poll();
if (task != null) {
task.run();
}
task = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void cancel() {
this.flag = false;
interrupt();
}
}
public static void main(String[] args) {
CustomThreadPoolExecutor poolExecutor = new CustomThreadPoolExecutor(5);
Integer count = 10;
CountDownLatch countDownLatch = new CountDownLatch(count);
AtomicInteger atomicInteger = new AtomicInteger(1);
for (int i = 0; i < count; i++) {
poolExecutor.execute(() -> {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
System.out.println("task-" + atomicInteger.getAndIncrement() + ";thread name is " + Thread.currentThread().getName());
});
}
try {
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("end =====>");
poolExecutor.shutdown();
}
}
三、 运行结果
task-4;thread name is Thread-3
task-5;thread name is Thread-0
task-3;thread name is Thread-2
task-1;thread name is Thread-4
task-2;thread name is Thread-1
task-7;thread name is Thread-1
task-6;thread name is Thread-4
task-8;thread name is Thread-2
task-9;thread name is Thread-0
task-10;thread name is Thread-3
end =====>
shutdown thread pool
Process finished with exit code 0