[java]FutureTask手引き裂き工場マルチスレッド面接問題

19749 ワード

ある大手電子商取引Javaの面接問題:主はマルチスレッドから協力して質問することが多い:顧客が注文サービス(OrderService)を要求し、サービス側はユーザーの身分(RemotePassportService)、ユーザーの銀行信用(RemoteBankService)、ユーザーのローンを検証する(RemoteLoanService).同時効率を向上させるために、3つのサービス検証作業を同時に行う必要があります.いずれかの検証が失敗した場合は、すぐに失敗を返します.そうしないと、すべての検証が終了し、正常に戻ります.Java実装が必要です.
ターゲット
  • マルチスレッド
  • 検証に失敗し、すぐに
  • に戻ります.
    主な技術点:
  • .FutureTaskのget()メソッドは、ブロックメソッドとCountDownLauchの原理の差が少なく閉鎖であり、FutureTaskのcancel()は残りのスレッド
  • を中断することができる.
    主な考え方
  • 3スレッドは対応する検証プログラムを同時に実行し、1つの検証に失敗した場合、Checkクラスのfail関数を呼び出し、他のプロセスを終了する.
  • 現在の局がtasksを遍歴している場合、getメソッドが割り込み異常を投げ出した場合、検証に失敗したことを示します.Checkクラスのfail関数が呼び出されていない場合は、検証に成功します.
  • public class FutureTask2 {
    	public static void main(String[] args) {
    		List<FutureTask<Boolean>> tasks = new ArrayList<FutureTask<Boolean>>();
    		FutureTask<Boolean> task1 = new FutureTask<Boolean>(new RemotePassportService());
    		FutureTask<Boolean> task2 = new FutureTask<Boolean>(new RemoteBankService());
    		FutureTask<Boolean> task3 = new FutureTask<Boolean>(new RemoteLoanService());
    		tasks.add(task1);
    		tasks.add(task2);
    		tasks.add(task3);
    		Check.setTasks(tasks);
    		new Thread(task1).run();
    		new Thread(task2).run();
    		new Thread(task3).run();
    		//   get  ,       Check.isFailed               
    		//  get                       cancel,  get      
    		//                 
    		for(FutureTask<Boolean> task:tasks){
    			try {
    				task.get();
    			} catch (Exception e) {break;}
    		}
    		if(Check.isFailed) System.out.println("    ");
    		else{System.out.println("    ");}
    	
    }
    }
    
    class RemotePassportService implements Callable<Boolean>{
    	Random r = new Random();
    	Check c;
    
    	public Boolean call() throws Exception {
    		Boolean flag = r.nextBoolean();//     
    		if(flag){System.out.println("      ");return true;}
    		else{
    			System.out.println("      ");
    			return Check.fail();
    	}
    	}
    }
    //    
    class RemoteBankService implements Callable<Boolean>{
    	Random r = new Random();
    	Check c;
    
    	public Boolean call() throws Exception {
    		Boolean flag = r.nextBoolean();
    		if(flag){System.out.println("      ");return true;}
    		else{
    			System.out.println("      ");
    			return Check.fail();
    	}
    	}
    }
    //    
    class RemoteLoanService implements Callable<Boolean>{
    	Check c;
    	Random r = new Random();
    
    	public Boolean call() throws Exception {
    		Boolean flag = r.nextBoolean();
    		if(flag){System.out.println("      ");return true;}
    		else{
    			System.out.println("      ");
    			return Check.fail();
    	}
    }
    }
    
    
    class Check{
    	static List<FutureTask<Boolean>> tasks;
    	public static Boolean isFailed = false;
    	public static Boolean fail(){
    		isFailed = true;
    		for(FutureTask<Boolean> task:tasks){
    			task.cancel(true);
    		}
    		return false;
    	}
    	public Boolean getIsFailed() {
    		return isFailed;
    	}
    	public static void setTasks(List<FutureTask<Boolean>> tasks) {
    		Check.tasks = tasks;
    	}
    	
    }
    

    2019/10/8更新
    このdemoはよく理解できないかもしれません
    実はgetを巡回するのは主スレッドのCheckを保証するためである.isFailedは、サブスレッドの実行が完了した後に実行されます.FutureTaskのgetメソッドはブロックメソッドなので.スレッドの検証に失敗すると、Checkが呼び出されます.fail()メソッドは、他の検証作業をキャンセルし、メインスレッドがgetにある場合、ミッドレンジ異常をキャプチャした場合、ある検証に失敗したことを示します.直接終了、印刷チェックに失敗しました
    いずれかの検証に失敗したかどうかについては、すぐに失敗を返します.答えははい.
    スレッドのrunメソッドを呼び出すと、3つのスレッドが同時に実行され、あるスレッドの検証に失敗した場合.すべてのスレッドが実行されなくなります.フロントgetが届くと中端異常が投げ出されます.コレクション内のgetが最初に実行されるわけではありません.2番目のスレッドが最初に検証に失敗すると、すべての実行スレッドがキャンセルされ、getが着いた最初のスレッドがミッドレンジ異常を投げ出し、印刷検証に失敗します.
    だからこのdemoは完全に要求に合っています!!!