以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Java/Eclipse 』  (http://bbs.xml.org.cn/list.asp?boardid=41)
----  线程池的实现  (http://bbs.xml.org.cn/dispbbs.asp?boardid=41&rootid=&id=84110)


--  作者:卷积内核
--  发布时间:4/2/2010 11:22:00 AM

--  线程池的实现
线程池也许很多比较陌生 但是提到servlet每个人都知道,servlet就是用线程池来处理请求的
一个线程池由线程池管理器 工作线程 任务队列和任务接口组成
一 线程池管理器---ThreadPoolMananger 主要负责启动 停止工作线程
Java代码
public class ThreadPoolManager {   
  
    private static int DEFAULT_POOL_SIZE = 4;   
    private List<WorkThread> threadPool;   
    private Queue<Task> taskQueue;   
    private int poolSize;   
       
    public ThreadPoolManager(){   
        this(DEFAULT_POOL_SIZE);   
    }   
       
    public ThreadPoolManager(int poolSize){   
        if(poolSize <= 0){   
            this.poolSize = DEFAULT_POOL_SIZE;   
        }else{   
            this.poolSize = poolSize;   
        }   
           
        threadPool = new ArrayList<WorkThread>(this.poolSize);   
        taskQueue = new ConcurrentLinkedQueue<Task>();   
           
        startup();   
    }   
       
    /**  
     * 启动线程池 开始处理任务  
     */  
    private void startup(){   
        System.out.println("启动工作线程。。。");   
        synchronized(taskQueue){   
            for(int i = 0; i < DEFAULT_POOL_SIZE; i++){   
                WorkThread workThread = new WorkThread(taskQueue);   
                threadPool.add( workThread );   
                workThread.start();   
            }   
        }   
           
    }   
       
    /**  
     * 停止工作线程。工作线程不一定立即停止,只有在线程处于运行状态时会立即停止  
     */  
    public void shutdown(){   
        System.out.println("停止工作线程.");   
        synchronized(taskQueue){   
            for(int i = 0; i < DEFAULT_POOL_SIZE; i++){   
                threadPool.get(i).shutdown();   
            }   
        }   
    }   
       
    /**  
     * 添加消息到队尾,    
     */  
    public void addTask(Task task){   
        synchronized(taskQueue){   
            taskQueue.add(task);   
            taskQueue.notifyAll();     
        }   
    }   
  
}  

public class ThreadPoolManager {

 private static int DEFAULT_POOL_SIZE = 4;
 private List<WorkThread> threadPool;
 private Queue<Task> taskQueue;
 private int poolSize;
 
 public ThreadPoolManager(){
  this(DEFAULT_POOL_SIZE);
 }
 
 public ThreadPoolManager(int poolSize){
  if(poolSize <= 0){
   this.poolSize = DEFAULT_POOL_SIZE;
  }else{
   this.poolSize = poolSize;
  }
  
  threadPool = new ArrayList<WorkThread>(this.poolSize);
  taskQueue = new ConcurrentLinkedQueue<Task>();
  
  startup();
 }
 
 /**
  * 启动线程池 开始处理任务
  */
 private void startup(){
  System.out.println("启动工作线程。。。");
  synchronized(taskQueue){
   for(int i = 0; i < DEFAULT_POOL_SIZE; i++){
    WorkThread workThread = new WorkThread(taskQueue);
    threadPool.add( workThread );
    workThread.start();
   }
  }
  
 }
 
 /**
  * 停止工作线程。工作线程不一定立即停止,只有在线程处于运行状态时会立即停止
  */
 public void shutdown(){
  System.out.println("停止工作线程.");
  synchronized(taskQueue){
   for(int i = 0; i < DEFAULT_POOL_SIZE; i++){
    threadPool.get(i).shutdown();
   }
  }
 }
 
 /**
  * 添加消息到队尾,  
  */
 public void addTask(Task task){
  synchronized(taskQueue){
   taskQueue.add(task);
   taskQueue.notifyAll();  
  }
 }

}


二 工作线程---WorkerThread 顾名思义 它本身就是一个线程,而且是专门用来工作的,工作线程的主要任务是从任务队列中取出任务 然后执行任务
Java代码
/**  
* 工作线程  
* @author XuLiangYong  
* Jul 20, 2007 3:47:52 PM  
*/  
public class WorkThread extends Thread{   
    private boolean shutdown = false;   
    private Queue<Task> queue;   
       
    public WorkThread(Queue<Task> queue){   
        this.queue = queue;   
    }   
       
    public void run(){   
        while(!shutdown){   
            synchronized(queue){ //获得对象锁 禁止其他线程访问   
                if(!queue.isEmpty()){   
                    //处理任务    
                    Task task = queue.poll();   
                    task.execute();   
                }else{   
                    try {   
                        queue.wait(); //释放锁 线程处于阻赛状态 等待notify唤醒   
                    } catch (InterruptedException e) {   
                    }   
                }   
            }   
        }//end while   
    }   
       
    /**  
     * 调用该方法后不一定会立即结束线程, 只有在线程处于运行状态且处理完当前任务后才结束  
     */  
    public void shutdown(){   
        shutdown = true;   
    }   
}  

/**
* 工作线程
* @author XuLiangYong
* Jul 20, 2007 3:47:52 PM
*/
public class WorkThread extends Thread{
 private boolean shutdown = false;
 private Queue<Task> queue;
 
 public WorkThread(Queue<Task> queue){
  this.queue = queue;
 }
 
 public void run(){
  while(!shutdown){
   synchronized(queue){ //获得对象锁 禁止其他线程访问
    if(!queue.isEmpty()){
     //处理任务
     Task task = queue.poll();
     task.execute();
    }else{
     try {
      queue.wait(); //释放锁 线程处于阻赛状态 等待notify唤醒
     } catch (InterruptedException e) {
     }
    }
   }
  }//end while
 }
 
 /**
  * 调用该方法后不一定会立即结束线程, 只有在线程处于运行状态且处理完当前任务后才结束
  */
 public void shutdown(){
  shutdown = true;
 }
}

三 任务队列---TaskQueue FIFO数据结构 在出对入队的时候要锁定对象避免两个线程重复处理某任务
在这里我采用的是java提供的ConcurrentLinkedQueue队列,这是一个用链表实现的队 可无限的扩大,具体用法请看doc
用到队列的地方主要有两个 addTask(Task task) 和 Task task = queue.poll();

四 任务接口---Task 任务接口只有一个方法 execute(),使用者只需实现这个接口就可以了
Java代码
public interface Task {   
    void execute();   
}  

public interface Task {
 void execute();
}

用法:
Java代码
public class TestThreadPoolManager extends TestCase {   
       
    public void test(){   
        ThreadPoolManager pool = new ThreadPoolManager();   
        for(int i = 0; i < 100; i++){   
            pool.addTask(new SimpleTask(new MyManager(), i)); //SimpleTask实现了Task接口   
        }   
        pool.shutdown();   
    }   
       
}  

public class TestThreadPoolManager extends TestCase {
 
 public void test(){
  ThreadPoolManager pool = new ThreadPoolManager();
  for(int i = 0; i < 100; i++){
   pool.addTask(new SimpleTask(new MyManager(), i)); //SimpleTask实现了Task接口
  }
  pool.shutdown();
 }
 
}
可以看出用户的使用非常简单  
在jdk5中 java提供了线程池 有时间再写一个jdk5的线程池的例子
有一点注意 千万不要在servlet中调用线程池  因为servlet本来就是一个线程池


W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.125ms