If you are comfortable with Rx, you could use RxJava. It's not pretty, but it works:
final ExecutorService executor = Executors.newCachedThreadPool();
final ConnectableObservable<?> result = Observable.concat(
Observable.defer(
new Func0<Observable<?>>() {
@Override
public Observable<?> call() {
return Observable.from(
executor.submit(
new Runnable() {
@Override public void run() { task(1); }
}
)
);
}
}
),
Observable.defer(
new Func0<Observable<?>>() {
@Override
public Observable<?> call() {
return Observable.from(
executor.submit(
new Runnable() {
@Override public void run() { task(2); }
}
)
);
}
}
)
).replay();
result.connect();
There is probably a better way to do this, but I don't know the RxJava APIs very well, as I use my own implementation of Rx for Java.
The gist is:
- The
concat()
operator joins multiple observable sequences in serial. In this case, each sequence is just a single element: the result of a task. - The
defer()
operator prevents each task from being scheduled until someone subscribes. In this case, that happens when the preceding task/sequence terminates. - The
from()
operator transforms aFuture<?>
into anObservable<?>
. - The
replay()
operator creates a connectable observable, ensuring that the sequence of tasks only executes once, even if there are multiple subscribers. The result will be captured so late subscribers will still receive it. - Calling
connect()
kicks off the sequence of tasks.