1. 实现第一版基础的线程池
1.1 首先我们定义一个线程池类ThreadPool,然后线程池有一个容器存放我们创建的线程,另一个容器则是存放当前线程池需要处理的任务队列,线程容器用ArrayList实现,任务队列容器用LinkedList实现。
1.2 线程池功能分析:创建线程池时,往线程容器中加入默认数量的线程,但是由于此时的任务队列为空,所以线程处于等待状态;当往线程池提交任务时,唤醒正在等待的线程来处理任务,处理完任务后如果任务队列为空,线程又进入等待状态,代码及运行结果如下。
import java.util.ArrayList;
import java.util.LinkedList;
public class ThreadPoolTest {
public static void main(String[] args) {
// 创建线程池
ThreadPool threadPool = new ThreadPool();
// 提交任务给线程池处理
for (int i = 0; i < 40; i++) {
threadPool.submit(String.valueOf(i));
}
}
}
class ThreadPool{
private static final int DEFAULT_SIZE = 10;
private int size;
private final static ThreadGroup GROUP = new ThreadGroup("MyThreadGroup");
private final LinkedList<String> taskQueue = new LinkedList<>();
private ArrayList<Thread> threadLst = new ArrayList<>();
ThreadPool(){
this(DEFAULT_SIZE);
}
ThreadPool(int size){
this.size = size;
for (int i = 0; i < size; i++) {
Thread t = new Thread(GROUP, ()->{
while(true){
synchronized (taskQueue) {
// 任务队列为空,线程则进入等待状态
while (taskQueue.isEmpty()) {
try {
taskQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 模拟处理任务
System.out.println(Thread.currentThread().getName() + " deal task!!");
taskQueue.removeFirst();
}
// 如果这一段业务代码处于synchronized内,那么会导致提交任务时抢不到锁,
// 而造成提交任务被打断
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " finish task!");
}
});
threadLst.add(t);
t.start();
}
}
public void submit(String task){
// 多线程下提交任务和处理任务,需要加synchronized保证线程安全。
// 提交任务后需要唤醒线程处理任务
synchronized (taskQueue){
taskQueue.add(task);
taskQueue.notify();
System.out.println("提交了一个任务========");
}
}
}