论坛首页 Java企业应用论坛

线程池的实现

浏览 8810 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-07-23  
OO
线程池也许很多比较陌生 但是提到servlet每个人都知道,servlet就是用线程池来处理请求的
一个线程池由线程池管理器 工作线程 任务队列和任务接口组成
一 线程池管理器---ThreadPoolMananger 主要负责启动 停止工作线程
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 顾名思义 它本身就是一个线程,而且是专门用来工作的,工作线程的主要任务是从任务队列中取出任务 然后执行任务
/**
 * 工作线程
 * @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(),使用者只需实现这个接口就可以了
public interface Task {
	void execute();
}


用法:
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本来就是一个线程池
   发表时间:2007-07-24  
LZ的思路,是线程共享任务队列,线程按同步方法获取一个非空的任务执行:工作线程自己去“拉单”干。

我提供另外一种思路,线程是被动,由别人(监工)分配,激发:

有一个主线程--“监工”:负责查看任务队列中是否有任务,如果有,取出一个任务,设置到一个“空闲”的线程中,并notify该线程。

while (hasTask) {
   1、get the task from task quene 
   2、get an waiting worker thread, or create a new workder thread
   3、set the task to the thread, and set the thread status running
   synchronized(thread) {
       4、thread.nofity();//not notifyAll()
   }
}




线程类的run方法会是这样的:
synchronized(this) {
    while (!shutdown) {
        if (status == running) {
           1、run the task;
           2、task = null;
           3、status = waiting;
           4、manager.done(this, task);//告知监工自己已经完成这个任务
       }
       5、this.wait();
    }
}
0 请登录后投票
   发表时间:2007-07-24  
ls这种方式倒是比较独特 用另外一种思路解决这个问题
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics