目标:构建一个简单的线程池
功能如下:
- 可提交Runnable任务。
- 任务队列,需要支持DualStack与DualQueue。
- 线程队列,最小线程数(一直存在),可扩展线程数。
- 根据任务量调整线程量,任务繁忙线程数扩展到最大线程数,任务空闲清空所有空闲的扩展线程。
任务队列简述:
LinkedTransferQueue
- DualQueue:双向结构,公平的(先进先出),需要使用tryTransfer才是DualQueue的模式,调用offer就相当于普通的LinkedBlockingQueue。
SynchronousQueue
- DualQueue:双向结构,公平的(先进先出),创建SynchronousQueue时,传入true——new SynchronousQueue(true)
- DualStack:非公平的,栈式,先进后出。创建SynchronousQueue时,传入true——new SynchronousQueue(flase)
代码实现:
package com.miracle.study.queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Miracle
* @date 2021/4/17 12:56
*/
public class Scheduler {
/**
* 任务队列,可替换使用SynchronousQueue以及其他并发队列
*/
private LinkedTransferQueue<Runnable> queue;
/**
* 可创建的扩展线程数
*/
private AtomicInteger extendThread;
/**
* 线程队列
*/
private ArrayBlockingQueue<Thread> threadQueue;
public Scheduler(int minThread, int maxThread) {
queue = new LinkedTransferQueue<>();
// 线程管理队列
threadQueue = new ArrayBlockingQueue<>(maxThread);
// 计算扩展线程数量
extendThread = new AtomicInteger(maxThread - minThread);
// 创建常驻线程
for (int i = 0; i < minThread; i++) {
addThread(false);
}
}
/**
* 添加线程
* @param isExtend
*/
public void addThread(boolean isExtend){
var thread = new Thread(new Work(isExtend));
threadQueue.add(thread);
thread.start();
}
/**
* 提交任务
* @param task
*/
public void submit(Runnable task) {
// 尝试添加任务,添加任务是否成功取决于是否有消费者在等待。
while (!queue.tryTransfer(task)) {
// 将可扩展线程数量自减一并获取
var i = extendThread.decrementAndGet();
// 判断是否仍然可以创建扩展线程
if (i >= 0) {
// 创建扩展线程
addThread(true);
}else {
// 扩展线程数量自加一
extendThread.incrementAndGet();
Thread.onSpinWait();
}
}
}
class Work implements Runnable {
/**
* 是否是扩展线程,用于判断是否要在空闲时删除。
*/
private boolean isExtend;
public Work(boolean isExtend){
this.isExtend = isExtend;
}
@Override
public void run() {
System.out.println(Thread.currentThread() + " Start");
// 循环任务
while (runByQueue()) {
}
// 移除线程
threadQueue.remove(Thread.currentThread());
System.out.println(Thread.currentThread() + " Over");
// 可创建的扩展线程数+1
extendThread.incrementAndGet();
}
public boolean runByQueue(){
try {
// 尝试获取任务,最长等待时间1秒
var task = queue.poll(1, TimeUnit.SECONDS);
// 判断是否成功获取任务
if (task != null) {
// 运行任务
task.run();
// 判断是否是扩展线程,如果是就直接退出循环,结束当前线程,因为当前线程已经获取不到任务了。
} else if (isExtend) {
return false;
} else {
// 线程等待一个CPU周期
Thread.onSpinWait();
}
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
}
public static void main(String[] args) throws InterruptedException {
Scheduler scheduler = new Scheduler(5, 10);
for (int i = 0; i < 100; i++) {
scheduler.submit(() -> {
try {
System.out.println("success");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
Thread.sleep(3000);
for (int i = 0; i < 100; i++) {
scheduler.submit(() -> {
try {
System.out.println("success");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}