È possibile scrivere un metodo, che esegue alcuni task di lunga durata in modo asincrono. Dovresti quindi restituire un oggetto futuro, che è vuoto ma viene riempito quando l'attività di lunga durata è completata. In altri linguaggi di programmazione, questo è chiamato una promessa.
Ecco un semplice esempio. Ho creato un metodo chiamato someLongAsyncOperation
che esegue qualcosa che richiede un po 'di tempo. Per simulare questo, dormo solo per 3 secondi prima di generare una risposta.
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;
}
}
}
Se si esegue questa piccola classe di test, vedrete, che someLongAsyncOperation
rendimenti veloci, ma quando si chiama future.get();
aspettiamo il completamento dell'operazione.
Ora è possibile eseguire qualcosa come l'avvio di più di un AsyncOperazione lunga, in modo che vengano eseguiti in parallelo. E poi aspetta che siano finiti tutti.
Questo funziona come punto di partenza per voi?
EDIT
Si potrebbe implementare someMethod
come questo:
public MyAnswer someMethod() throws ExecutionException, InterruptedException {
Future<MyAnswer> future = someLongAsyncOperation(); // kick of async operation
return future.get(); // wait for result
}
che renderà di nuovo l'operazione asincrona synchron, chiamandolo e in attesa del risultato.
EDIT2
Ecco un altro esempio che utilizza l'ora/notify:
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
attende fino receivedObject
esiste. receiveObject
notifica all'arrivo.
E 'un buon punto di partenza, ma sono sicuro su come il metodo di ricezione fornirebbe la someLongAsyncOperation con il suo risultato? – Anonomoose
Sembra che tu voglia ricevere "receiveObject" quando l'operazione è terminata. È più come una richiamata, piuttosto che un futuro.Fammi provare a fornire un esempio ... –
Sì, questo è quello che sto andando - scusa! – Anonomoose