[java]FutureTask手引き裂き工場マルチスレッド面接問題
19749 ワード
ある大手電子商取引Javaの面接問題:主はマルチスレッドから協力して質問することが多い:顧客が注文サービス(OrderService)を要求し、サービス側はユーザーの身分(RemotePassportService)、ユーザーの銀行信用(RemoteBankService)、ユーザーのローンを検証する(RemoteLoanService).同時効率を向上させるために、3つのサービス検証作業を同時に行う必要があります.いずれかの検証が失敗した場合は、すぐに失敗を返します.そうしないと、すべての検証が終了し、正常に戻ります.Java実装が必要です.
ターゲットマルチスレッド 検証に失敗し、すぐに に戻ります.
主な技術点: .FutureTaskのget()メソッドは、ブロックメソッドとCountDownLauchの原理の差が少なく閉鎖であり、FutureTaskのcancel()は残りのスレッド を中断することができる.
主な考え方 3スレッドは対応する検証プログラムを同時に実行し、1つの検証に失敗した場合、Checkクラスのfail関数を呼び出し、他のプロセスを終了する. 現在の局がtasksを遍歴している場合、getメソッドが割り込み異常を投げ出した場合、検証に失敗したことを示します.Checkクラスのfail関数が呼び出されていない場合は、検証に成功します.
2019/10/8更新
このdemoはよく理解できないかもしれません
実はgetを巡回するのは主スレッドのCheckを保証するためである.isFailedは、サブスレッドの実行が完了した後に実行されます.FutureTaskのgetメソッドはブロックメソッドなので.スレッドの検証に失敗すると、Checkが呼び出されます.fail()メソッドは、他の検証作業をキャンセルし、メインスレッドがgetにある場合、ミッドレンジ異常をキャプチャした場合、ある検証に失敗したことを示します.直接終了、印刷チェックに失敗しました
いずれかの検証に失敗したかどうかについては、すぐに失敗を返します.答えははい.
スレッドのrunメソッドを呼び出すと、3つのスレッドが同時に実行され、あるスレッドの検証に失敗した場合.すべてのスレッドが実行されなくなります.フロントgetが届くと中端異常が投げ出されます.コレクション内のgetが最初に実行されるわけではありません.2番目のスレッドが最初に検証に失敗すると、すべての実行スレッドがキャンセルされ、getが着いた最初のスレッドがミッドレンジ異常を投げ出し、印刷検証に失敗します.
だからこのdemoは完全に要求に合っています!!!
ターゲット
主な技術点:
主な考え方
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は完全に要求に合っています!!!