java网络编程学习笔记(四):线程池的实现
package QQ; import java.util.LinkedList; /** * Created by hu on 2015/11/9. */ public class ThreadPool extends ThreadGroup{ //线程池是否关闭 private boolean isClosed=false; //表示工作队列 private LinkedList<Runnable> workQueue; //表示线程池ID private static int threadPoolId; //表示工作线程ID private int threadId; public ThreadPool(String name) { super(name); } /** * poolSize指定线程池中工作线程的数目 * */ public ThreadPool(int poolSize){ this("ThreadPool-"+(threadPoolId++)); setDaemon(true); //创建工作队列 workQueue=new LinkedList<Runnable>(); for(int i=0;i<poolSize;i++){ //创建并启动工作线程 new WorkThread().start(); } } /** * 向工作队列中加入一个新任务,由工作线程去执行该任务 * */ public synchronized void execute(Runnable task){ //线程池被关闭则抛出异常 if(isClosed){ throw new IllegalStateException(); } if(task!=null){ //将任务添加到工作队列中去 workQueue.add(task); //唤醒正在getTask()方法中等待任务的工作线程 notify(); } } /** * 从工作队列中取出一个任务,工作线程会调用此方法 * */ protected synchronized Runnable getTask() throws InterruptedException { while (workQueue.size()==0){ if(isClosed) return null; //如果工作队列中没有任务,就等待任务 wait(); } //取出队列中的第一个任务 return workQueue.removeFirst(); } /** * 关闭线程池 * */ public synchronized void close(){ if(isClosed){ isClosed=true; //清空工作队列 workQueue.clear(); //中断所有工作进程,该方法继承自ThreadGroup类 interrupt(); } } /** * 等待工作进程把所有任务执行完 * */ public void join(){ synchronized (this){ isClosed=true; //唤醒还在getTask()方法中等待任务的工作进程 notifyAll(); } Thread[] threads=new Thread[activeCount()]; //enumerate()方法继承自ThreadGroup类,获得线程中当前所有活着的工作线程 int count=enumerate(threads); for(int i=0;i<count;i++){ try{ //等待工作线程运行结束 threads[i].join(); }catch (InterruptedException ex){ ex.printStackTrace(); } } } private class WorkThread extends Thread{ public WorkThread(){ //加入到当前ThreadPool线程组中 super(ThreadPool.this,"WorkThread-"+(threadPoolId++)); } public void run(){ while (!isInterrupted()){ Runnable task=null; try{ //取出任务 task=getTask(); }catch (InterruptedException ex){ ex.printStackTrace(); } //如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程 if(task==null) return; try{ //运行任务,异常在catch块中捕获 task.run(); }catch (Throwable t){ t.printStackTrace(); } } } } }