Javaスレッドプールの実装


スレッドプールの役割:
 
スレッドプールの役割は、システムで実行されるスレッドの数を制限することです.
システムの環境状況に応じて、スレッドの数を自動的にまたは手動で設定し、実行の最適な効果を達成することができます.スレッドが少なくなるとシステムリソースが浪費され、多くなるとシステムの混雑効率が低下します.スレッドプールでスレッド数を制御し、他のスレッドが待機するようにします.1つのタスクの実行が完了し、キューから先頭のタスクを取り出して実行を開始します.キューにタスク待機プロセスがない場合、スレッドプールのスレッドは待機します.新しいタスクが実行される必要がある場合、スレッドプールに待機している作業スレッドがあれば、実行を開始できます.そうでなければ待機キューに入ります.
 
 
スレッドプールを使用する理由:
 
スレッドの作成と破棄の回数を減らし、各作業スレッドを再利用し、複数のタスクを実行できます.また、システムの耐性に応じて、スレッドプール内のワークラインスレッドの数を調整し、メモリの消費が多すぎるため、サーバを疲れさせないようにすることもできます(スレッドごとに約1 MBのメモリが必要で、スレッドが開くほど、消費されるメモリが大きくなり、最後にハングアップします).
 
 
スレッドプールクラス
import java.util.LinkedList;

public class ThreadPool extends ThreadGroup {
	private boolean isClosed = false;  //        
	private LinkedList workQueue;      //    
	private static int threadPoolID = 1;  //    id
	public ThreadPool(int poolSize) {  //poolSize               

		super(threadPoolID + "");      //  ThreadGroup   
		setDaemon(true);               //      ,         
		workQueue = new LinkedList();  //      
		for(int i = 0; i < poolSize; i++) {
			new WorkThread(i).start();   //         ,                  
		}
	}
	
	/**              ,           */
	public synchronized void execute(Runnable task) {
		if(isClosed) {
			throw new IllegalStateException();
		}
		if(task != null) {
			workQueue.add(task);//          
			notify(); 			//      getTask()           
		}
	}
	
	/**             ,          */
	private synchronized Runnable getTask(int threadid) throws InterruptedException {
		while(workQueue.size() == 0) {
			if(isClosed) return null;
			System.out.println("    "+threadid+"    ...");
			wait();				//           ,     
		}
		System.out.println("    "+threadid+"      ...");
		return (Runnable) workQueue.removeFirst(); //          ,       
	}
	
	/**       */
	public synchronized void closePool() {
		if(! isClosed) {
			waitFinish();        //          
			isClosed = true;
			workQueue.clear();  //      
			interrupt(); 		//              ,      ThreadGroup 
		}
	}
	
	/**                */
	public void waitFinish() {
		synchronized (this) {
			isClosed = true;
			notifyAll();			//      getTask()            
		}
		Thread[] threads = new Thread[activeCount()]; //activeCount()                。
		int count = enumerate(threads); //enumerate()     ThreadGroup ,                           
		for(int i =0; i < count; i++) { //          
			try {
				threads[i].join();	//        
			}catch(InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 *    ,    ,            ,   
	 */
	private class WorkThread extends Thread {
		private int id;
		public WorkThread(int id) {
			//      ,        ThreadPool    
			super(ThreadPool.this,id+"");
			this.id =id;
		}
		public void run() {
			while(! isInterrupted()) {  //isInterrupted()     Thread ,         
				Runnable task = null;
				try {
					task = getTask(id);		//    
				}catch(InterruptedException ex) {
					ex.printStackTrace();
				}
				//  getTask()  null      getTask()    ,      
				if(task == null) return;
				
				try {
					task.run();  //    
				}catch(Throwable t) {
					t.printStackTrace();
				}
			}//  end while
		}//  end run
	}// end workThread
}

 
 
テストクラス
public class ThreadPoolTest {
	
	public static void main(String[] args) throws InterruptedException {
		ThreadPool threadPool = new ThreadPool(3); //      3        
		Thread.sleep(500); //  500  ,                
		//    
		for (int i = 0; i <=5 ; i++) { //  6   
			threadPool.execute(createTask(i));
		}
		threadPool.waitFinish(); //          
		threadPool.closePool(); //     

	}

	private static Runnable createTask(final int taskID) {
		return new Runnable() {
			public void run() {
				System.out.println("Task" + taskID + "  ");
				System.out.println("Hello world");
				System.out.println("Task" + taskID + "  ");
			}
		};
	}
}

 
原文住所:http://sunnylocus.iteye.com/blog/223327