単一のスレッドアプリケーションでは、メソッドを呼び出すと、結果は計算が終わったときにのみ返されます。
public string downloadcontents(url url)throws ioexception {trystream input = url.openstream()){return ioutils.tring(input、standardc harsets.utf_8);}} // ... final future <strong> contents = downloa url( "http://www.example.com");
DownloadContents()は無害に見えますが、長い間実行する必要があります。同時に、遅延を減らすために、待機結果中に、同時に他の作業を独立して処理する必要がある場合があります。過去には、新しいスレッドを開始するか、結果を待つことができます(メモリ、ロック、悪い待機()/notify()ペア)。
将来の<t>モードを通じて、それは明らかになります:
public static Future <string>起動ロード(URL URL){// ...}最終future <string> contentsFuture =起動ロード(new、http://www.example .com "); //その他。得る ();
起動ロード()、起動ロード()はブロックされることはありませんが、外部サイトが応答するのを待っています。 それどころか、それが迅速に戻り、軽量の未来<string>オブジェクトを返す場合。 このオブジェクトは約束であるため、将来の文字列タイプはいつになるかわかりませんが、結果に戻って戻るまでこのリファレンスを保持します。 言い換えれば、未来はエージェントまたはオブジェクトのパッケージであり、実際のターゲットオブジェクトではありません。非同期計算が完了したら、抽出できます。 では、Futureはどのようなインターフェイスを提供しますか?
future.get()は最も重要な方法です。約束の結果が利用可能になるまでブロックして待つので、この文字列が本当に必要な場合は、get()メソッドを呼び出して待機します。 また、タイムアウトパラメーターを受け入れる重い負荷バージョンもあります。
場合によっては、将来が利用可能かどうかをひそかに見たいと思うかもしれません。これは、isdone()を介して実行できます。状況を想像してください、あなたのユーザーはいくつかの非同期計算を待っています。
Final Future <string> contentsFuture =起動ロード(new URL( "http://www.example.com"); ;;
最後に、future.isdone()がtrueを返すため、future.get()の内容はすぐに戻ることが保証されます。このモデルに従っている場合、待機したり、毎秒Isdone()に電話するのに忙しくありません。
キャンセルファイストは、私たちがカバーしていない最後のものです。非同期作業を開始し、2秒後にしばらく待つことができると想像してください。しかし、あなたは良い市民です、あなたはこの将来のオブジェクトを伝えるべきです:私はもうあなたを必要としません、あなたは気にしません。 その後、時代遅れのタスクを停止することでリソースを保存できます。文法は簡単です:
contentsfuture.cancel(true);
私たちは皆、非表示にするのが好きです、ボーアタイプのパラメーター、そうですか?キャンセルは、2つの方法で実装できます。タスクが開始される前に、将来の結果が表明される前に計算が開始されると、誤ったパラメーターがキャンセルされます。 Callable.call()が半分に実行されると、Trueを通過させると、future.call()が侵入し、ランニング作業を中断しようとします。これは良いと思いますか? Phenomenaこの方法でブロックされていて、一部の人々が通話をキャンセルすることを決定したとしても、swree.sleep()、object.wait()、conition.await()などの悪名高い方法である中断のある方法を投げる人、彼らは間違いなく中断のエクセプトを投げ、現在の操作のタスクを中断するために誰かを送ります。
だから私たちは今、未来が何であるかを理解しています---プレースホルダー、あなたは将来ターゲットオブジェクトを取得できます。車のように、製造する鍵はありません。しかし、どのようにしてアプリケーションで未来のインスタンスを取得できますか? 最も一般的な2つのリソースは、スレッドプールと非同期メソッド(スレッドプールのサポート)です。したがって、起動loading()メソッドは次のように書き換えることができます。
プライベートファイナルエグゼクティブサービスプール= executors.newfixedthreadpool(10); inputstream input = url.openstream()){return ioutils.tostring(input、standardcharsets.utf_8);}});}
多くの退屈な文法の問題がありますが、基本的な考え方は簡単です。長い間実行する必要があるパッケージングコンピューティングは、調整可能な<string>に詰め込まれ、このスレッドプールに()を送信しますスレッド。 送信した後、Future <string>の実装は、何らかの方法でタスクとスレッドプールにリンクするようなものです。明らかに、あなたのタスクはすぐに実行されません。真ん中にとどまるタスクは、長い間実行されてきたタスクをキャンセルすることもできますが、これはより複雑なことです。
春とEJBの未来にも会うことができます。たとえば、@asyncの注釈をSpringフレームワークに追加できます。
@AsyncPublic Future <String>起動ロード(Final URL URL)throws ioException {try(inputstream input = url.openstream()){return new asyncres ult <>(ioutils.tosttring(input、standardcharsets.utf_8));}}}}}}}}
パッケージングの結果を通じて将来を単純に実装するだけでなく、この方法自体はスレッドプールや処理された非同期と相互作用しないことに注意してください。後で春は、スレッドプールで起動ロード()へのすべての呼び出しを表します。 EJBでは、@asynchronousannotationを追加することで同じ機能が完了します。