Class AsyncTimer
This object provides a futures which complete at specified times. This is useful for pausing amid
a chain of callback actions, i.e., between iterations of a loop. A critical tenant of
asynchronous reactive programming is to never block a thread, at least not for an indefinite
period of time. If an action blocks, it may prevent completion of other tasks in its executor's
queue, possibly resulting in deadlock. An easy and tempting way to accidentally block is to call
Object.wait()
or Thread.sleep(long)
when trying to wait for a specific period of
time. Unfortunately, this does not just block the chain, but blocks the thread. Java provides a
Timer
, but its Future
s are not CompletableFuture
s. The same is true of
ScheduledThreadPoolExecutor
.
A delay is achieved using mark()
, then AsyncTimer.Mark.after(long)
.
future.thenCompose(__ -> timer.mark().after(1000))
mark()
marks the current system time; all calls to the mark's AsyncTimer.Mark.after(long)
schedule futures relative to this mark. Scheduling a timed sequence of actions is best
accomplished using times relative to a single mark. For example:
Mark mark = timer.mark(); mark.after(1000).thenCompose(__ -> { doTaskAtOneSecond(); return mark.after(2000); }).thenAccept(__ -> { doTaskAtTwoSeconds(); });
This provides slightly more precise scheduling than delaying for a fixed period between tasks. Consider a second example:
Like Timer
, each AsyncTimer
is backed by a single thread which uses
Object.wait()
to implement its timing. Thus, this is not suitable for real-time
applications. Unlike Timer
, the backing thread is always a daemon. It will not prevent
process termination. If a task is long running, the sequence should queue it on another executor,
perhaps using CompletableFuture.supplyAsync(Supplier, Executor)
. Otherwise, other
scheduled tasks may be inordinately delayed.
-
Nested Class Summary
Nested Classes -
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionatSystemTime
(long timeMillis) Schedule a task to run whenSystem.currentTimeMillis()
has passed a given timemark()
Mark the current system time
-
Field Details
-
DEFAULT_TIMER
-
thread
-
-
Constructor Details
-
AsyncTimer
public AsyncTimer()Create a new timerExcept to reduce contention among threads, most applications need only create one timer instance. See
DEFAULT_TIMER
.
-
-
Method Details
-
atSystemTime
Schedule a task to run whenSystem.currentTimeMillis()
has passed a given timeThis method returns immediately, giving a future result. The future completes "soon after" the current system time passes the given time in milliseconds. There is some minimal overhead, but the scheduler endeavors to complete the future as close to the given time as possible. The actual scheduled time will not precede the requested time.
- Parameters:
timeMillis
- the time after which the returned future completes- Returns:
- a future that completes soon after the given time
-
mark
Mark the current system time- Returns:
- this same timer
-