多くの場合、プロジェクトには、実行するために非同期に実行される必要がある(スレッドプールに提出)する必要があるいくつかのタスクがありますが、メインスレッドは非同期実行の結果を知る必要があることがよくあります。現時点で私たちは何をすべきですか?実行可能で達成することは不可能です。次のコードを読むには、Callableを使用する必要があります。
java.util.concurrent.callable; import java.util.concurrent.executionexception; import java.util.concurrent.executorservice; Import java.util.concurrent.executors; Import Java.util.concurrent.future; public class addcask empteger public addtask(int a、int b){this.a = a; this.b = b; } @Override public Integer Call Sthrows Exception {integer result = a + b;返品結果; } public static void main(string [] args)throws arturtedexception、executionexception {executorservice executor = executors.newsinglethreadexecutor; // JDKはこれまでに戻ってきており、FutureTask Future <integer> future = executor.submit(new addtask(1、2))のインスタンスです。 integer result = future.get; //未来のステータスが完了した場合のみ(future.isdone = true)、getメソッドが返されます}}}非同期実行結果を取得するという要件を認識できますが、通知メカニズムを提供しないため、この未来は実際には有用ではないことがわかりました。 java.util.concurrent.future.futureのインターフェイス方法をご覧ください。
パブリックインターフェイスFuture <v> {booleanキャンセル(boolean may interrumpifrunning);ブールイスキャンセル;ブールイスドーン; v get interruptedexception、executionexception; v get(長いタイムアウト、タイムニットユニット)断続的なエクセプト、executionexception、timeoutexception;}このことから、JDKの将来のメカニズムは実際には使いやすくないことがわかります。この将来にリスナーを追加して、リスナーが完了したときにリスナーに通知させることができれば、以下のiFutureと同じように使いやすくなります。
将来のパッケージ; java.util.concurrent.cancellationexception; Import java.util.concurrent.future; import java.util.current.timeunit;/***非同期操作の結果。 * * @author lixiaohui * @param <v>実行結果のタイプパラメーター */public interface ifuture <v>拡張<v> {boolean issuccess; // v getNowが成功したかどうか。 //結果をすぐに返します(将来が完成した状態であるかどうかに関係なく)スロー可能な原因。 //実行障害の理由はキャンセル可能です。 // ifuture <v>をキャンセルすることはできますか? //将来の完了を待っているブールン待ち(長いタイムアウトミリ)は、中断されたエクセプトをスローします。 //タイムアウト将来の完了ブールン待ち待ち待機(ロングタイムアウト、タイムニットタイムニット)が断続的なエクセプトをスローします。 ifuture <v> awaitun -interrumdibly; //将来の完了を待っている、中断ブールンは途切れないように待つことはありません(長いタイムアウトミリス); ifuture <v> addlistener(ifuturelistener <v> l); //将来が完了すると、これらの追加されたリスナーにIfuture <v> removelistener(ifuturelistener <v> l)が通知されます。 }次に、このiFutureを一緒に実装しましょう。この前に、将来の実装全体の元のコアはこれら2つの方法であるため、Object.Wait、Object.NotifyAllメソッドを説明します。 JDKの説明を見てください:
パブリッククラスオブジェクト{ /** *別のスレッドが * {@link java.lang.object#notify}メソッドを呼び出すまで、現在のスレッドが待機します。 *言い換えれば、このメソッドは、単に * @code wait(0)}を実行する単純に *実行されるかのように正確に動作します。 *このメソッドを呼び出した後、現在のスレッドはオブジェクトモニターロックをリリースし、CPU使用権を放棄します。別のスレッドがnotify/ notifyall */ public final void wayがcurtrededexceptionを呼び出すまで{wait(0); } /***このオブジェクトのモニターで待っているすべてのスレッドを目覚めさせます。 * {@code wait}メソッドのいずれかを呼び出すことにより、 *スレッドはオブジェクトのモニターで待機します。 * <p> *目覚めたスレッドは、現在の *スレッドがこのオブジェクトのロックを放棄するまで続行できません。目覚めたスレッド *は、このオブジェクトで同期するために積極的に競合する可能性のある他のスレッドと通常の方法で競合します。たとえば、 *目覚めたスレッドは、このオブジェクトをロックする次のスレッドであることにおいて、信頼できる特権や欠点を享受しません。 */パブリックファイナルネイティブvoid notifyall;}これを知った後、私たちは自分で未来を実装するというアイデアがあります。スレッドがifuture.awaitなどの一連のメソッドを呼び出す場合、未来が完了していない場合は、future.waitメソッドを呼び出して、スレッドに待機状態に入るようにします。他のスレッドが将来を完了状態に設定した場合(ここでの完了状態には通常の終わりと異常な端が含まれていることに注意してください)、future.notifyallメソッドを呼び出す必要があります。完全な実装は次のとおりです(コードを理解するのは難しくありません。私は将来のネットのメカニズムを参照します。興味がある場合は、Nettyのソースコードを確認できます):
将来のパッケージ; java.util.collection; import java.util.concurrent.cancellationexception; import java.util.concurrent.copyonwritearraylist; import.executionexception; Import java.util.current.current.time <pre> *通常の端で、実行結果がnullでない場合、結果は実行結果です。実行結果がnullの場合、result = {@link abstractfuture#success_signal} *例外が終了すると、結果は{@link cassholder}のインスタンスになります。キャンセルのために例外が終了した場合、結果は{@link cancellationexception}のインスタンスである場合、それ以外の場合は他の例外のインスタンスです *次の状況により、非同期操作が完成した状態に転送されます。 </li> * <li>非同期操作が正常に終了した場合(SetSuccess Method)</li> * <li>非同期操作が異常に終了する場合(SetFailure Method)</li> * </ul> * * * @author lixiaohui * * @asynchronous execute class absoctution ifuture <v> {保護された揮発性オブジェクトの結果; //可視性が保証される必要があります/ ***リスナーセット*/保護されたコレクション<ifutureListener <v >>リスナー= new CopyOnWriteArrayList <IfutureListener <v >>; / ***タスクの通常の実行結果がnull、つまりクライアントが{@link abstractfuture#setSucses(null)}を呼び出すとき、*結果参照*/ private static final successsignal success_signal = new successignal; @Override public booleanキャンセル(boolean may interpuntruptifrunning){if(isdone){// return falseはキャンセルできません。 } synchronized(this){if(isdone){// return falseを再確認します。 } result = new causholder(new cancellationexception); notifyall; // isdone = true、オブジェクトの待機を待っているスレッドに通知} notifyListeners; //非同期操作が完了したことをリスナーに通知します。 } @Override public boolean iscancellable {return result == null; } @Override public boolean iscancelled {return result!= null && sults instance of cassholder &&((compsholder)result)。 } @Override public boolean isdone {return result!= null; } @Override public v get strows arturnedexception、executionexception {await; //実行結果が投げられる原因=原因を待ちます。 if(couse == null){//例外は発生しませんでしたが、非同期操作は通常復帰します。 } if(cansanceof cancellationexception){//非同期操作はキャンセルされた(cancellationexception)原因。 }新しいexecutionException(cause); //その他の例外} @Override public v get(long timeout、timeunit unit)arturnedexception、executionexception、timeoutexception {if(await(unit)){//実行結果が待機可能な原因=原因を待っています。 if(couse == null){//例外は発生しませんでしたが、非同期操作は通常復帰します。 } if(cansanceof cancellationexception){//非同期操作はスロースロー(cancellationexception)原因をキャンセルされました。 } new executionException(cause); //その他の例外}をスローする} //時間はまだ終わっていません。 } @Override public boolean issuccess {return result == null? false:!(result instance of bassholder); } @suppresswarnings( "Unchecked")@Override public v getNow {return(v)(result == success_signal?null:result); } @Override public Throwable cause {if(result!= null && result instance of causholder){return((causholder)result).cause; } nullを返します。 } @Override public ifuture <v> addlistener(ifuturelistener <v>リスナー){if(listener == null){throw new nullpointerexception( "reaster"); } if(isdone){// notifyListener(リスナー)を完了した場合。これを返します。 } synchronized(this){if(!isdone){ristens.add(listener);これを返します。 }} notifyListener(リスナー);これを返します。 } @Override public ifuture <v> removelistener(ifuturelistener <v>リスナー){if(listener == null){throw new NullPointerException( "ristener"); } if(!isdone){ristens.remove(ristener); }これを返します。 } @override public ifuture <v> await interruptedexception {return wait0(true); } private ifuture <v> await0(boolean gurtredable)arturnedexception {if(!isdone){//完了した場合、端末が許可され、中断された場合、割り込みの例外がスローされる場合、IF(中断可能&&スレッド。 } boolean挿入= false;同期(this){while(!isdone){try {wait; //ロックをリリースして待機状態を入力し、他のスレッドがオブジェクトのnotify/notifyallメソッドを呼び出すのを待ちます/catch(arternedexception e){if(arterntable){show e; } else {挿入= true; }}}}} if(邪魔){//ここで割り込みフラグを設定する必要があるのはなぜですか?待機方法から戻った後、割り込みフラグがクリアされたため、//ここで他のコードが中断されていることがわかります。 thread.currentthread.interrupt; }}これを返します。 } @Override public boolean await(long timeoutmillis)throws arturtedexception {return await0(timeunit.milliseconds.tonanos(timeoutmillis)、true); } @Override public boolean await(long timeout、timeunit unit)throws arturtedexception {return await0(unit.tonanos(タイムアウト)、true); } private boolean await0(long timeoutnanos、boolean interruteable)arturtededexception {if(isdone){return true; } if(timeoutnanos <= 0){return isdone; } if(割り込み可能&&スレッド。 } long starttime = timeoutnanos <= 0? 0:system.nanotime; long waittime = timeoutnanos;ブールインタード= false; try {synchronized(this){if(isdone){return true; } if(waittime <= 0){return isdone; } for(;;){try {wait(waittime / 1000000、(int)(waittime%1000000)); } catch(arturtedexception e){if(arterntable){throw e; } else {挿入= true; }} if(isdone){return true; } else {waittime = timeoutnanos-(system.nanotime -starttime); if(waittime <= 0){return isdone; }}}}}} finally {if(挿入){thread.currentthread.interrupt; }}} @override public ifuture <v> waituninterrumdibly {try {return wait0(false); } catch(arternedexception e){//ここに例外がスローされている場合、それは処理できない、新しいjava.lang.internalerrorを投げることはできません。 }} @Override public boolean waitun -unterractibly(long timeoutmillis){try {return await0(timeunit.milliseconds.tonanos(timeoutmillis)、false); } catch(arturnedexception e){新しいjava.lang.internalerror; }} @Override public boolean waitun -unterctibly(long timeout、timeunit unit){try {return wait0(unit.tonanos(timeout)、false); } catch(arturnedexception e){新しいjava.lang.internalerror; }}保護されたifuture <v> setFailure(スロー可能な原因){if(setFailure0(cause)){notifyListeners;これを返します。 }新しいIllegalStateExceptionを投げます( "既に完了:" + this); } private boolean setFailure0(スロー可能な原因){if(isdone){return false; } synchronized(this){if(isdone){return false; } result = new causholder(cause); notifyall; } trueを返します。 }保護されたifuture <v> setSuccess(object result){if(setsuccess0(result)){// notifylisteners sulcient;これを返します。 }新しいIllegalStateExceptionを投げます( "既に完了:" + this); } private boolean setsuccess0(object result){if(isdone){return false; } synchronized(this){if(isdone){return false; } if(result == null){//非同期操作の通常の実行の結果はnull this.result = success_signal; } else {this.result = result; } notifyall; } trueを返します。 } private void notifyListeners {for(ifuturelistener <v> l:リスナー){notifylistener(l); }} private void notifyListener(ifuturelistener <v> l){try {l.operationcompleted(this); } catch(例外e){e.printstacktrace; }} private static class successsignal {} private static final class causholder {final throwable cause; causholder(スロー可能な原因){this.cause = couse; }}}では、これをどのように使用するのですか?上記のスケルトンの実装により、さまざまな非同期結果をカスタマイズできます。以下は遅延したタスクです。
future.test; import future.ifuture; import future.ifuturelistener;/** * delay delay * @author lixiaohui * */public class delaydder {public static void main(string [] args){new Delaydder.add(3 * 1000、1、2).addlistener(new ifutureristener voidener> voidener> OperationCompleted(Ifuture <Integer> Future)スロー{system.out.println(future.getNow)}); } / ***遅延追加* @param遅延期間ミリ秒* @param a addition* @param b追加* @return Asynchronous result* / public delayAdditionFuture Add(long delay、int a、int b){delayadditionfuture future = new DelayAdditionFuture;新しいスレッド(new DelayAdditionTask(Delay、A、B、Future))。start;未来を返す; }プライベートクラスDelayAdditionTask Runnable {Private Long Delay; private int a、b;プライベートディレイアジションフューチャーフューチャー。 public DelayAdditionTask(Long Delay、Int A、Int B、DelayAdditionFuture Future){super; this.delay = delay; this.a = a; this.b = b; this.future = future; } @Override public void run {try {thread.sleep(delay);整数i = a + b; // TODOここに将来の設定が完了ステータスに設定されています(通常の実行が完了します)future.setSucces(i); } catch(arturnedexception e){// todoここに完了ステータスに設定された将来のセット(例外が完了)future.setfailure(e.getCause); }}}} package future.test; import future.abstractfuture; import future.ifuture; // 2つの方法を外部のクラスDelayAdditionFuture extends AbstractFuture <integer> {@Override public ifuture <integer> setsuckes(object result){return super.etsucess(result); } @Override public ifuture <integer> setFailure(スロー可能な原因){return super.setfailure(cause); }}クライアントは、将来が完了したかどうかを積極的に尋ねる必要がないことがわかりますが、将来が完了したときにOperationCompletedメソッドを自動的に呼び戻すことができます。クライアントは、コールバックにロジックを実装する必要があります。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。