对于大家来说,或多或少都知道Executor框架下的线程池。下面我介绍一下如何写一个线程池,因为这个问题的解决方法里有一个非常好的模型,相对来说这里的对象池的思想和生产者消费者关系模型也是非常重要的。
概念
在操作系统中,线程是操作系统调度的最小单元,同时线程也是一种受限的系统资源,即线程不能无限的生产,而且线程的创建和销毁都会有相对应的开销。
实现
在线程池中,我们的线程对象是可复用的。那么怎么复用呢?想明白这个就可以实现一个线程池了。对于这个问题,我们先按照:结构分析,结构概要图,详实实现来解决
结构分析
对于结构分析,主要是考虑可能涉及的对象、变量,功能。对于线程池的结构是比较容易猜测到的。
对象、变量:1.线程对象Thread(线程的对象池);2.被执行的Runnable集合;
功能:添加Runnable,执行任务,关闭任务
如果基于自己使用的ThreadPool来说,我们的结构可能不一样。主要是体现在功能上:添加Runable(execute(Runnable)),关闭任务shutdown()
在对象和功能进行分析后,他们两个点相互补充,譬如,关闭任务当然有一个变量来标记的,所以在对象上进行添加。
结构概要图
添加一点,在execute的时候,进行Notify任务队列。
详细实现
这就是代码了
package com.owant.java.study.thread.threadpool.div;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by owant on 3/23/16.
* <p/>
* 1.存在的线程
* 2.管理存在线程的执行者
* <p>
* <p>
* 主要是复用对象Thread的对象池,每一个Thread对象是一个工作者
* 进行循环,如果没有任务进入await状态,在main线程进行execute的时候进行notify
*/
public class DefaultThread<Job extends Runnable> implements ThreadPool<Job> {
private static final int max_worker_numbers = 10;
private static final int default_worker_numbers = 5;
private static final int min_worker_numbers = 1;
//循序表,记录加入的任务
private final LinkedList<Job> jobs = new LinkedList<>();
//工作者的列表
private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());
private int workerNum = default_worker_numbers;
//原子量,每一个线程都能操作,用于生产编号
private AtomicLong threadNum = new AtomicLong();
public DefaultThread() {
initializeWorker(default_worker_numbers);
}
public DefaultThread(int num) {
workerNum = num >= max_worker_numbers ? max_worker_numbers :
(num <= min_worker_numbers ? min_worker_numbers : num);
initializeWorker(workerNum);
}
/**
* 创建线程池里的线程
*
* @param num
*/
private void initializeWorker(int num) {
for (int i = 0; i < num; i++) {
Worker worker = new Worker();
//添加进入工作者集合
workers.add(worker);
Thread thread = new Thread(worker, "ThreadPool-Worker-" + threadNum.incrementAndGet());
//工作者开始工作
thread.start();
}
}
@Override
public void execute(Job run) {
if (run != null) {
synchronized (jobs) {
jobs.addLast(run);
jobs.notify();
}
}
}
@Override
public void shudown() {
for (Worker w : workers) {
w.shutdown();
}
}
@Override
public void addWorkers(int num) {
}
@Override
public void removedWorkers(int num) {
}
@Override
public int getJobSize() {
return 0;
}
private class Worker implements Runnable {
private volatile boolean runflag = true;
@Override
public void run() {
//一直在循环
while (runflag) {
Job job = null;
synchronized (jobs) {
while (jobs.isEmpty()) {
try {
jobs.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
return;
}
}
job = jobs.removeFirst();
}
if (job != null) {
job.run();
}
}
}
public void shutdown() {
runflag = false;
}
}
}