長時間実行されているタスクを非同期的に起動するメソッドを記述できます。その後、空の状態ですが、長時間実行されているタスクが完了すると、オブジェクトが返されます。他のプログラミング言語では、これは約束と呼ばれます。
ここは簡単な例です。私はsomeLongAsyncOperation
というメソッドを作成し、それはしばらく時間がかかるものを実行します。これをシミュレートするには、私は答えを生成する前に3秒間寝るだけです。
import java.util.UUID;
import java.util.concurrent.*;
public class Test {
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
public Future<MyAnswer> someLongAsyncOperation(){
Future<MyAnswer> future = executorService.submit(() -> {
Thread.sleep(3000);
return new MyAnswer(UUID.randomUUID().toString());
});
return future;
}
public static void main(String[] args) throws Exception {
System.out.println("calling someLongAsyncOperation ...");
Future<MyAnswer> future = new Test().someLongAsyncOperation();
System.out.println("calling someLongAsyncOperation done.");
// do something else
System.out.println("wait for answer ...");
MyAnswer myAnswer = future.get();
System.out.printf("wait for answer done. Answer is: %s", myAnswer.value);
executorService.shutdown();
}
static class MyAnswer {
final String value;
MyAnswer(String value) {
this.value = value;
}
}
}
あなたは、この小さなテストクラスを実行する場合は、someLongAsyncOperation
戻って速いこと、わかりますが、future.get();
を呼び出すときに、私たちは操作が完了するのを待ちます。
これで、複数のlongAsyncOperationの開始のようなことができるようになり、並列実行が可能になりました。そしてすべてが完了するまで待ってください。
これは出発点として機能しますか?
あなたはこのようなsomeMethod
を実装することができ
EDIT:それを呼び出し、結果を待つことによって、再び非同期操作シンクロンを行います
public MyAnswer someMethod() throws ExecutionException, InterruptedException {
Future<MyAnswer> future = someLongAsyncOperation(); // kick of async operation
return future.get(); // wait for result
}
。
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test2 {
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
private Object receivedObject;
private final Object mutex = new Object();
public static void main (String[] args) throws InterruptedException {
Object obj = new Test2().someMethod();
System.out.println("The object is" + obj + ", wooh!");
executorService.shutdown();
}
public void callObject() {
System.out.println("callObject ...");
// Sends request for the object asynchronously!
executorService.submit(() -> {
// some wait time to simulate slow request
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// provide object to callback
receiveObject(UUID.randomUUID().toString());
});
System.out.println("callObject done.");
}
public void receiveObject(Object object) {
System.out.println("receiveObject ...");
synchronized (mutex) {
this.receivedObject = object;
mutex.notify();
}
System.out.println("receiveObject done.");
}
public Object someMethod() throws InterruptedException {
System.out.println("someMethod ...");
synchronized (mutex) {
callObject();
while(this.receivedObject == null){
mutex.wait();
}
}
System.out.println("someMethod done.");
return this.receivedObject;
}
}
someMethod
待つreceivedObject
が存在するまで:ここ
EDIT2
は、通知/待機使用する別の例です。 receiveObject
到着時に通知します。
それは良い出発点ですが、私は受信方法は、その結果とsomeLongAsyncOperationを提供する方法についてはわからないんですか? – Anonomoose
操作が完了したときに 'receiveObject'を呼び出すように思えます。これは将来の代わりにコールバックに似ています。私は例を提供しようとしましょう... –
ええ、それは私が行っているものです - ごめんなさい! – Anonomoose