1 手写多线程
1.1 流程梳理:
1. 创建MyThreadExecutor线程池类
2. 【定义成员变量】:
初始化线程数量;
链表阻塞队列;
结束线程池标识;
2. 【创建有参构造方法】
初始化线程数量,并调用“线程任务内部类”;
3. 【创建“线程任务内部类”】
用于执行阻塞队列中的任务;
4. 【创建添加任务方法execute()】;
5. 【创建销毁线程池方法shutdown()】
代码实现
/**
* 自定义线程池
* @author 祁
*/
public class MyThreadExecutor {
// 核心线程数
private volatile int corePoolSize;
// 任务队列
private final BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
// 结束标识,结束的策略:当flag为false时并且任务全部执行完后再关闭线程池。
private volatile boolean flag = true;
// 有参构造创建线程池,并初始化核心线程数
MyThreadExecutor(int corePoolSize){
this.corePoolSize = corePoolSize;
for (int i = 0; i < corePoolSize; i++) {
MyTask myTask = new MyTask();
myTask.start();
}
}
// 添加任务方法
public void execute(Runnable runnable) throws InterruptedException {
workQueue.put(runnable);
}
// 关闭线程池方法
public void shutdown(){
this.flag = false;
}
// 内部线程类,用于执行任务
class MyTask extends Thread{
@Override
public void run() {
while (workQueue.size() > 0 || flag){
// 获取需要执行的任务
Runnable poll = workQueue.poll();
if (poll != null){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
poll.run();
}
}
}
}
}
测试
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程开始");
// 创建自定义线程池,核心线程数2
MyThreadExecutor myThreadExecutor = new MyThreadExecutor(2);
for (int i = 0; i < 5; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
// 将任务添加到线程池
myThreadExecutor.execute(runnable);
}
// 关闭线程池
myThreadExecutor.shutdown();
System.out.println("主线程结束");
}
优化
while (workQueue.size() > 0 || flag)
这段代码非常损耗性能,不管队列有没有任务都会一直循环运行。
解决:
将:Runnable poll = workQueue.poll();
改为:Runnable poll = workQueue.take(); // take()若队列为空,则阻塞线程,直到获取到元素*