Spójrz na CountDownLatch. Można emulować żądaną synchronicznego zachowanie z mniej więcej tak:
private CountDownLatch doneSignal = new CountDownLatch(1);
void main() throws InterruptedException{
asyncDoSomething();
//wait until doneSignal.countDown() is called
doneSignal.await();
}
void onFinishDoSomething(){
//do something ...
//then signal the end of work
doneSignal.countDown();
}
można również osiągnąć ten sam problem przy użyciu CyclicBarrier
z 2 stron tak:
private CyclicBarrier barrier = new CyclicBarrier(2);
void main() throws InterruptedException{
asyncDoSomething();
//wait until other party calls barrier.await()
barrier.await();
}
void onFinishDoSomething() throws InterruptedException{
//do something ...
//then signal the end of work
barrier.await();
}
Jeśli masz kontrolę nad kodu źródłowego z asyncDoSomething()
Zaleciłbym jednak przeprojektowanie go w celu zwrócenia obiektu Future<Void>
. W ten sposób można łatwo przełączać się między zachowaniem asynchronicznym/synchronicznym, gdy jest to potrzebne:
void asynchronousMain(){
asyncDoSomethig(); //ignore the return result
}
void synchronousMain() throws Exception{
Future<Void> f = asyncDoSomething();
//wait synchronously for result
f.get();
}
+1 Dzięki za tak szczegółową odpowiedź, rodion! – hpique
Chciałbym móc dać ci więcej niż 1 głos. Doskonała rekomendacja Future –
@rodion, jeśli użyję CountDownLatch wewnątrz pętli i utworzę instancję w pętli, czy zatrzyma ona pętlę od wykonania kolejnej iteracji, dopóki zadanie iteracji nie zostanie wykonane lub będzie dalej kontynuowało iterację? Daj mi znać, jeśli moje pytanie nie jest jasne. – Aaron