package com.sxt.Tread;
import java.util.LinkedList;
/**
* @author jt
*2015-12-5 下午5:43:33
*
*/
//线程池的实现方案,ThreadGroup表示一个线程的集合
public class ThreadPol extends ThreadGroup {
private boolean isClose=false;//线程池是否关闭
private LinkedList<Runnable>workQueue;//表示工作队列
private static int threadPolID;//表示线程ID
private int threadID;//表示工作线程ID
/**
* @param name
*/
public ThreadPol(int polSize) {
super("ThreadPool"+(threadPolID++));
//调用父类的 setDaemon()方法(更改此线程组的后台程序状态)
//参数:daemon - 如果为 true,则表示此线程组是一个后台程序线程组;否则,表示此线程组是一个普通线程组。
//创建一个Runnable类型的队列
workQueue=new LinkedList<Runnable>();
for(int i=0;i<polSize;i++)
{
new WorkThred().start();//创建并启动工作线程
}
}
/*向工作队列中加入一个新任务,由工作线程去执行该任务*/
public synchronized void execute(Runnable task)
{
if(isClose)//线程被关闭则抛出IllegalStateException
{
//java.lang.IllegalStateException异常, 该异常表示,当前对客户端的响应已经结束,
//不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容。
throw new IllegalStateException();
}
if(task!=null)
{
workQueue.add(task);
notify();//唤醒正在getTask()方法中等待任务的工作线程
}
}
/*向工作队列中取出一个任务,工作任务会调用此方法*/
protected synchronized Runnable getTask() throws InterruptedException
{
while(workQueue.size()==0)
{
if(isClose)
{
return null;
}
wait();//如果工作队列中没有任务,就等待任务
}
return workQueue.removeFirst();
}
/**关闭线程池*/
public synchronized void close()
{
if(!isClose)
{
isClose=true;
workQueue.clear();
interrupt();
}
}
/*等待工作线程把所有任务执行完*/
public void join()
{
synchronized(this){
isClose=true;
notifyAll();//唤醒还在getTask()方法中等待任务的工作线程
}
//activeCount()返回此线程组中活动线程的估计数。
//结果并不能反映并发活动,并且可能受某些系统线程的存在状态的影响
Thread[] threads=new Thread[activeCount()];
//enumerate()继承ThreadGroup类,获得线程组中当前所有活着的工作线程
int count=enumerate(threads);
for(int i=0;i<count;i++)
{
try {
threads[i].join();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*内部类:工作线程*/
private class WorkThred extends Thread
{
public WorkThred()
{
//加到当前ThreadPol线程组中
super(ThreadPol.this,"WorkThred"+(threadID++));
}
public void run()
{
while(!isInterrupted())//isInterrupted()是继承Thread类的,判断线程是否中断
{
Runnable task=null;
try {
task=getTask();
} catch (Exception e) {
e.printStackTrace();
}
//如果getTask()返回null或者线程执行getTask()被中断,则结束此线程
if(task==null)
return ;
try {
task.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
在上面类中定义了一个LinkedList类型的workQueue成员变量,它表示工作队列,用来存放线程池要执行的任务,每个任务都是Runnable实例。ThreadPol类的客户程序(利用ThreadPol来执行任务的程序)只需要调用ThreadPol类的execute(Runnable task)的方法,就能向线程池提交任务。在ThreadPol类的execute()方法中,先判断线程池是否关闭,。如果线程池关闭就不再接受任务,否则就把任务加入工作队列中,并且唤醒正在等待任务的工作线程。
在ThreadPol类的构造方法中,会创建并启动若干工作线程,工作线程的数目由构造方法的参数polSize决定。WorkThred类表示工作线程,它是ThreadPol类的内部类。工作线程从工作队列中取出一个任务,接着执行该任务,然后在从工作队列中取出下一个任务并且执行它,如此反复。
工作线程从工作队列中取任务的操作是由ThreadPol类的getTask()方法实现的。它的处理逻辑如下:
1.如果队列为空并且线程池已经关闭,那就返回null,表示已经没有任何任务可以执行了;
2.如果队列为空并且线程池没有关闭,那就在此等候,直到其他线程将其唤醒或者中断;
3.如果队列中有任务,就取出第一个任务并将其返回;
线程池的join()方法和close()方法都可以用来关闭线程。join()方法确保在关闭线程池之前,工作线程把队列中的所有任务都执行完。而close()方法则立即清空队列,并且中断所有的工作线程。
ThreadPol类是GroupThread类的子类。GroupThread类表示线程组,它提供一些管理线程组中线程的方法。例如,interrupt()方法相当于调用线程组中所有活着的线程的interrupt()方法。线程池中的所有工作线程都加入到当前ThreadPol对象表示的线程组中。ThreadPol类在close()方法中调用interrupt()方法:
/**关闭线程池*/
public synchronized void close()
{
if(!isClose)
{
isClose=true;
workQueue.clear();
interrupt();
}
}
以上 interrupt()方法用于中断所有的工作线程。 interrupt()方法会工作线程造成以下影响:
1.如果此时一个工作线程正在ThreadPol的getTask()方法中因为执行wait()方法而阻塞,则会抛出InterruptException异常
2.如果一个工作线程正在执行一个任务,并且这个任务不会被阻塞,那么这个工作线程会正常执行完任务,但是在执行下一林while(!isInterrupted()){.........}时,由于isInterrupted()方法返回true,因此退出while循环。
测试程序:
package com.sxt.Tread;
/**
* @author jt
*2015-12-5 下午6:57:42
*
*/
public class ThreadPolTest {
/**
* @param args
*/
public static void main(String[] args) {
if(args.length!=2)
{
System.out.println(
"用法: +java ThreadPolTest numTasks polsize");
System.out.println("" +
"numTasks.integer:任务数");
return ;
}
int numTasks=Integer.parseInt(args[0]);
System.out.println("aaa"+numTasks);
int polSize=Integer.parseInt(args[1]);
System.out.println("bbb"+polSize);
ThreadPol threadPol=new ThreadPol(polSize);//创建线程池
//运行任务
for(int i=0;i<numTasks;i++)
{
threadPol.execute((createTask(i)));
}
threadPol.join();
//threadPol.close();
}
//定义一个简单的任务
private static Runnable createTask(final int taskID)
{
return new Runnable(){
@Override
public void run() {
System.out.println("Task"+taskID+" :start");
try {
Thread.sleep(500);
} catch (Exception e) {
System.out.println("Task"+taskID+" :end");
}
}
};
}
}