我们首先实现一个能简单执行任务的线程池,很明显,这样的线程池需要具备两个要素,一个是工作线程,一个是任务队列
//工作线程
private List<Thread> workers;
//任务队列
private final BlockingQueue<Runnable> taskQueue;
复制代码
工作线程用于执行具体的每一个任务,而任务队列负责接收要执行的任务。
线程池实例化的时候,确定线程池工作线程个数poolSize和最大允许接受任务的个数maxAccept
public MyThreadPool(int poolSize, int maxAccept) {
workers = new ArrayList<>(poolSize);
taskQueue = new ArrayBlockingQueue<>(maxAccept);
this.poolSize = poolSize;
this.maxAccept = maxAccept;
}
复制代码
工作线程在线程池的初始化方法中创建和启动
public synchronized void init() {
if(!inited) {
for (int i = 0; i < this.poolSize; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
//从任务队列中取任务,然后执行
Runnable runnable = taskQueue.take();
runnable.run();
} catch (InterruptedException e) {
}
}
}
});
workers.add(t);
t.start();
}
} else {
return;
}
inited = true;
}
复制代码
线程池对外提供执行任务的方法
public void execute(Runnable runnable) throws RejectException{
if(this.taskQueue.size() < maxAccept) {
this.taskQueue.add(runnable);
} else {
//线程池任务队列满了,抛出拒绝异常
throw new RejectException();
}
}
复制代码
实例化线程池,并调用
public static void main(String[] args) {
MyThreadPool myThreadPool = new MyThreadPool(5,50);
myThreadPool.init();
try {
myThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("任务被执行了");
}
});
} catch (MyThreadPool.RejectException e) {
}
}
复制代码
以上,我们实现了一个最简单的线程池
按照我们上一章中提到的,一个完备的线程池除了任务的执行之外,还应该具备以下条件
- 线程的生命周期管理,主要包括创建和回收
- 线程池的生命周期,初始化,执行,销毁等
显然,本例子中,并没有完整地体现线程和线程池的生命周期,我们实现的还有缺陷,下一章针对本部分进行完善。