javaマルチスレッド学習-----初めてスレッド池に入る


もっと読む
  
スレッドを使う
   最近のプロジェクトはコードの最適化をしています.業務機能があります.大体20台の内線が交換台にファイルを送ります.交換機はファイルを受け取った後、内線にデータの処理状況をフィードバックします.
    この時はスケジュールを使って、交換台に届いたメッセージを調べたいです.処理後、各内線に送ります.待ち時間を避けるために、マルチスレッドを使って、スレッドを使って管理します.
   
スレッドを作成
    資料を検索した後、JDK 1.5のjava.util.co ncurrentパッケージを用いてスレッド池を作成し、この例では固定スレッド数を再利用できるスレッド池を使用して、コードは以下の通りである.
	private static int maxThreads = 20;	//     
	private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);	//               
   
タスク実行結果を取得
    そして、FutureTaskクラスを使ってタスク実行結果を取得し、タスクタイムアウト時間を設定できます.コードは以下の通りです.
FutureTask ft = new FutureTask(thread,true);
e.execute(ft);
Boolean fTaskResult = ft.get();  //       ,      ,    
//Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS);  //      ,      ,        ,    ,    TimeoutException  
    もしタスクがタイムアウトしたら、私たちはFutureTaskクラスのcancelを呼び出すことができます.
    パラメータmayInterruptIfRunning-このタスクを実行するスレッドを中断すべきなら、trueです.さもなければ実行中のタスクの実行が完了します.コードは以下の通りです.
catch (TimeoutException e) {
		System.out.println("           ,        ");
		ft.cancel(true);
}
   しかし、このように問題があるのは、FutureTaskオブジェクトのget()メソッドを呼び出すと、タスクが完了するまでスレッドがブロックされ、他のスレッドの実行が停止され、オンライン検索で結果がない場合は、スレッドをもう一つ開けて、FutureTaskオブジェクトのget()を実行する方法である.コードは以下の通りである.
	/**
	 *     
	 * @param t	    
	 */
	public static void beginTask(Thread t){
		e.execute(t);
	}
	
	/**
	 *             
	 * @param key	    
	 * @param t		    
	 */
	public static void beginTask(String key,Thread thread){
		final String fKey = key;
		final FutureTask ft = new FutureTask(thread,true);
		runningTaskMap.put(key, ft);	//      
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get();
					if(fTaskResult){
						System.out.println("key :"+fKey+"       ");						
					}
				} catch (InterruptedException e) {
					System.out.println("              ");
				} catch (ExecutionException e) {
					System.out.println("         ,       ");
				}finally{
					runningTaskMap.remove(fKey);	//      
				}
			}
		});
	}
  
タスクフラグ
   また、実行中のジョブを取得するために、各タスクに対してマークを付けて、mapセットに保存します.コードは以下の通りです.
	//             
	private static Map> runningTaskMap = Collections.synchronizedMap(new HashMap>());
   スレッドプールを呼び出すたびに、mapセットに記録を保存し、呼び出しが完了したら削除します.
   私たちはまた、マークによって実行中のタスクを中断することができます.コードは以下の通りです.
	/**
	 *          ,       
	 * @param key	    
	 */
	public static void intteruptTask(String key){
		FutureTask ft = runningTaskMap.get(key);
		ft.cancel(true);
		if(ft.isDone()){
			runningTaskMap.remove(key);
		}
	}
   最後に完全なコードを添付します.
package task.concurrent.threadPoor;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FixedThreadPool {
	private static int maxThreads = 20;	//     
	private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);	//               
	
	//             
	private static Map> runningTaskMap = Collections.synchronizedMap(new HashMap>());
	
	/**
	 *     
	 * @param t	    
	 */
	public static void beginTask(Thread t){
		e.execute(t);
	}
	
	/**
	 *             
	 * @param key	    
	 * @param t		    
	 */
	public static void beginTask(String key,Thread thread){
		final String fKey = key;
		final FutureTask ft = new FutureTask(thread,true);
		runningTaskMap.put(key, ft);	//      
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get();
					if(fTaskResult){
						System.out.println("key :"+fKey+"       ");						
					}
				} catch (InterruptedException e) {
					System.out.println("              ");
				} catch (ExecutionException e) {
					System.out.println("         ,       ");
				}finally{
					runningTaskMap.remove(fKey);	//      
				}
			}
		});
	}
	
	/**
	 *             
	 * @param key		    
	 * @param thread	    
	 * @param timeout	 
	 */
	public static void beginTask(String key, Thread thread, int timeout) {
		final String fKey = key;
		final int fTimeout = timeout;
		final FutureTask ft = new FutureTask(thread,true);
		runningTaskMap.put(key, ft);	//      
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS);
					if(fTaskResult){
						System.out.println("key :"+fKey+"       ");						
					}
				} catch (InterruptedException e) {
					System.out.println("              ");
				} catch (ExecutionException e) {
					System.out.println("         ,       ");
				} catch (TimeoutException e) {
					System.out.println("           ,        ");
					ft.cancel(true);
				}finally{
					runningTaskMap.remove(fKey);	//      
				}
			}
		});
	}
	
	/**
	 *          ,       
	 * @param key	    
	 */
	public static void intteruptTask(String key){
		FutureTask ft = runningTaskMap.get(key);
		ft.cancel(true);
		if(ft.isDone()){
			runningTaskMap.remove(key);
		}
	}
	
	/**
	 *      
	 */
	public static void shutDownPool(){
		e.shutdown();
	}
}
   まとめ:呼び出しとテストコードは貼り付けません.スレッドの池コードを書くのは初めてですので、足りないところがたくさんあります.
   参考資料:http://blog.csdn.net/hemingwang0902/article/details/4557304
http://westyi.iteye.com/blog/714935
寄り添って歩幅も千里もない