JDK提供了线程池,为了了解线程池的运行原理,现在分析一个使用ThreadGroup实现的线程池
1.ThreadGroup
线程组可以遍历线程,获取活动或非活动的线程
activeCount()返回线程池组中线程数目
enumerate(Thread[])列举线程组中的线程
2.下面的线程池实现原理
构造方法
传递需要创建的线程数及队列,启动线程
线程内部类
Thread的继承,run方法循环执行从队列中取出的任务
取任务方法
从队列中取得任务,需要线程安全,供线程调用。如果一个线程取不到,则wait等待notify的唤醒,并是否锁
添加任务方法
添加任务到队列中, 添加完notify随机唤醒一个线程,提示有新的任务了
等待任务完成
notifyAll唤醒线程,使用了线程组来管理等待线程执行完毕
关闭线程池
清空队列,interrupt中断全部线程
3.线程池的使用
创建线程池,线程池只负责执行,业务逻辑封装成Runnable对象,线程池中的线程通过调用Runnable中的run方法执行
4.参考源码
public class ThreadPool extends ThreadGroup{
// 用于判断线程池是否关闭
private boolean isClosed = false;
// 任务队列
private LinkedList<Runnable> queue;
// 线程池ID
private static int threadPoolId;
// 线程ID
private int threadId;
// 通过构造方法传递创建线程数
public ThreadPool(int poolSize){
super("thread pool -" + threadPoolId++);
// 设为守护线程
setDaemon(true);
// 任务队列
queue = new LinkedList<Runnable>();
// 启动线程
for(int i=0;i<poolSize;i++){
new WorkThread().start();
}
}
// 任务执行的线程
private class WorkThread extends Thread{
public WorkThread(){
super("work thread-" + threadId++);
}
@Override
public void run() {
// 如果当前线程没有被中断,当调用了interrupt时线程会中断
while(!isInterrupted()){
Runnable task = null;
// 不断的从任务队列中取得任务
try {
task = getTask();
} catch (InterruptedException e) {
}
if(task == null){
return;
}
// 执行任务
task.run();
}
}
}
// 从队列中取任务,取任务需要线程安全,同一个任务只能被一个线程取到
protected synchronized Runnable getTask() throws InterruptedException{
while(queue.size()==0){
// 线程池已经关闭
if(isClosed){
return null;
}
// 为空,则等待,释放琐
wait();
}
return queue.removeFirst();
}
// 队列中添加任务
public synchronized void addTask(Runnable task){
if(isClosed){
throw new IllegalStateException();
}
if(task!=null){
queue.add(task);
// 已经添加任务,唤醒线程执行,notify并不能确定唤醒哪一个
// 唤醒wait的线程
notify();
}
}
// 等待任务执行完毕
public void join(){
// 关闭线程池
synchronized(this){
isClosed = true;
notifyAll();
}
// activeCount估算正在活动的线程
Thread[] threads = new Thread[activeCount()];
// 枚举,获得活动线程的引用,返回活动线程数目
int count = enumerate(threads);
for(int i=0;i<count;i++){
try {
// 等待线程结束
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 关闭线程池
public synchronized void close(){
if(!isClosed){
isClosed = true;
queue.clear();
// 中断线程
interrupt();
}
}
}
使用线程池执行任务
public static void main(String[] args) throws Exception{
// 创建线程池
ThreadPool pool = new ThreadPool(3);
for(int i=0;i<10;i++){
pool.addTask(task(i));
}
// 等待完成,关闭线程池
pool.join();
pool.close();
}
private static Runnable task(final int taskId){
return new Runnable(){
@Override
public void run() {
System.out.println("第"+taskId+"个任务,开始运行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第"+taskId+"个任务,运行结束");
}
};
}