You can use the Object.wait() method to achieve this behavior:
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
synchronized (this) { // needed to prevent an IllegalMonotirStateException (see https://stackoverflow.com/a/1537133/8178842)
wait();
}
}
catch (InterruptedException e) {
// should never happen
throw new RuntimeException(e);
}
});
A simple UnitTest shows the behavior:
@Test
public void test() {
// create a CompeltableFuture that just waits
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
synchronized (this) {// needed to prevent an IllegalMonotirStateException (see https://stackoverflow.com/a/1537133/8178842)
wait(); // wait till the CompletableFuture.complete method is called (or till this thread is notified, what shouldn't happen)
}
}
catch (InterruptedException e) {
// should never happen
throw new RuntimeException(e);
}
});
new Thread(() -> {
try {
Thread.sleep(3000); // wait for three seconds
}
catch (InterruptedException e) {
// ignore
}
// complete the future manually after three seconds
future.complete(null);
}).start();
try {
future.get(); // block until the future is completed
}
catch (InterruptedException | ExecutionException e) {
// can be ignored here
}
// the future.get() method will be blocking for 3 seconds
}
Because of the suspended thread that completes the CompletableFuture, the test will wait for 3 seconds and then finish waiting.