基于JUC,手写一个简单线程池
上代码
//自定义线程池
//模拟线程数量的控制 , 防止过多的资源创建和回收过程
public class ThreadExec {
//线程集合 可以统一管理 已创建的线程
private List<Runnable> tList;
public List<Runnable> gettQueue() {
return tList;
}
public BlockingQueue<Runnable> getWartQueue() {
return wartQueue;
}
//任务队列 超出任务队列将拒绝
private BlockingQueue<Runnable> wartQueue;
//tLen 线程数量 , wLen 任务队列数量
public ThreadExec(int tLen,int wLen){
this.tList = new ArrayList(tLen);
this. wartQueue = new ArrayBlockingQueue(wLen);
for (int i = 0; i < tLen; i++){
Thread t = new Thread(() ->{
new ThreadTask(this).start();
});
t.start();
tList.add(t);
}
}
//线程池 执行 方法
public void exec(Runnable t) {
//加入 任务队列 如果任务队列已满 则 不进行加入
wartQueue.offer(t);
}
}
//线程镜像类
class ThreadTask{
private ThreadExec threadExec;
public ThreadTask(ThreadExec threadExec){
this.threadExec = threadExec;
}
public void start(){
//获得任务队列
BlockingQueue<Runnable> wartQueue = threadExec.getWartQueue();
while (true){
try {
//从任务队列中获取任务 如果 队列为空则进入阻塞状态 直到拿到为止
Runnable t = wartQueue.take();
//执行 run 方法
t.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadPoll {
//原子类
public static AtomicInteger atomicInteger = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
//阻塞队列 线程数量 10个 阻塞队列 20 个线程任务
ThreadExec texec = new ThreadExec(10,20);
//创建30个线程 同时测试是否有线程安全问题 测试发现没有
for (int i = 0; i < 30; i++){
texec.exec(() -> {
atomicInteger.getAndIncrement();
//尝试 睡眠 1秒 占有线程资源 阻止最后10个线程进入
// 因为线程池支持最大容量 为 10个线程同时执行 20个任务队列
// 但是进来了30个线程 那么最后 10个线程 将会拒绝执行 预期输出 atomicInteger 为 20 代表线程池工作正常
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
//睡眠两秒等待结果查看
Thread.sleep(3000);
//输出 2000
System.out.println(atomicInteger.get());
}
}
JUC 当中 很多的api 线程的通信已经帮我们把繁琐的步骤封装好了,主要思路为
1.定义一个容器存储已创建的线程。
2.存储任务队列。
有了这两个基本就可以做一个简单的池子出来,核心保证队列是FIFO,这样就可以每个线程执行完毕后,空闲出来不用销毁然后执行下一个任务,减少线程的创建和销毁的性能开销。