Class DelayedAction
- All Implemented Interfaces:
Runnable
A "delayed action" is a some action that needs to get done by some time in the future.
This class does two things:
- It collapses multiple attempts to schedule the action into a single scheduled action, i.e., at most one outstanding scheduled action can exist at a time.
- It provides a race-free and 100% reliable way to
cancel()
a future scheduled action, if any.
The action itself is defined by the subclass' implementation of run()
.
To avoid races, this class requires the user to supply a locking object. This may either be a normal
Java object, in which case normal Java synchronization is used, or a Lock
object. The locking object is
used to serialize scheduling activity and action invocation. In other words, the locking object is locked during
the execution of schedule()
, cancel()
, and run()
.
Therefore, any time the locking object is locked, the state of this DelayedAction
instance is "frozen"
in one of three states: not scheduled, scheduled, or executing (in the latter case, of course the thread doing the
executing is the one holding the lock). Therefore, to completely avoid race conditions, user code must itself
lock the locking object itself prior to invoking any methods in this class.
Typically the most convenient locking object to use is the user's own this
object, which can be locked using a
synchronized
method or block.
Note: in the case that run()
invokes Object.wait()
on the locking object, thereby
temporarily releasing the lock, to any other methods in this class it will appear as if that execution has already
completed.
-
Constructor Summary
ModifierConstructorDescriptionprotected
DelayedAction
(Object lock, ScheduledExecutorService executorService) Constructor utitilizing aScheduledExecutorService
and normal Java object locking.protected
DelayedAction
(Object lock, TaskScheduler taskScheduler) Constructor utitilizing aTaskScheduler
and normal Java object locking.protected
DelayedAction
(Lock lock, ScheduledExecutorService executorService) Constructor utitilizing aScheduledExecutorService
and aLock
for locking.protected
DelayedAction
(Lock lock, TaskScheduler taskScheduler) Constructor utitilizing aTaskScheduler
and aLock
for locking. -
Method Summary
Modifier and TypeMethodDescriptionvoid
cancel()
Cancel the future scheduled action, if any.Get the scheduled time for the outstanding scheduled action, if any.boolean
Determine whether there is currently an outstanding scheduled action.protected ScheduledFuture<?>
Schedule the given action using the task scheduler passed to the constructor.void
Schedule the delayed action for the given time.
-
Constructor Details
-
DelayedAction
Constructor utitilizing aTaskScheduler
and normal Java object locking.- Parameters:
lock
- locking object used to serialize activity, or null forthis
taskScheduler
- scheduler object- Throws:
IllegalArgumentException
- iftaskScheduler
is null
-
DelayedAction
Constructor utitilizing aScheduledExecutorService
and normal Java object locking.- Parameters:
lock
- locking object used to serialize activity, or null forthis
executorService
- scheduler object- Throws:
IllegalArgumentException
- ifexecutorService
is null
-
DelayedAction
Constructor utitilizing aTaskScheduler
and aLock
for locking.- Parameters:
lock
- locking object used to serialize activitytaskScheduler
- scheduler object- Throws:
IllegalArgumentException
- iflock
is nullIllegalArgumentException
- iftaskScheduler
is null
-
DelayedAction
Constructor utitilizing aScheduledExecutorService
and aLock
for locking.- Parameters:
lock
- locking object used to serialize activityexecutorService
- scheduler object- Throws:
IllegalArgumentException
- iflock
is nullIllegalArgumentException
- ifexecutorService
is null
-
-
Method Details
-
schedule
Schedule the delayed action for the given time.More precisely:
- If an action currently executing, before doing anything else this method blocks until it completes; if this behavior is undesirable, the caller can avoid this behavior by synchronizing on the locking object prior to invoking this method.
- If no action is scheduled, one is scheduled for the given time.
- If an action is already scheduled, and the given time is on or after the scheduled time, nothing changes.
- If an action is already scheduled, and the given time is prior to the scheduled time, the action is rescheduled for the earlier time.
The net result is that, for any invocation, this method guarantees exactly one execution of the action will occur approximately on or before the given instant; however, multiple invocations of this method prior to action execution can only ever result in a single "shared" action.
- Parameters:
instant
- scheduled execution time (at the latest)- Throws:
IllegalArgumentException
- ifinstant
is nullTaskRejectedException
- if the given task was not accepted for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
-
cancel
public void cancel()Cancel the future scheduled action, if any.More precisely:
- If an action currently executing, before doing anything else this method blocks until it completes; if this behavior is undesirable, the caller can avoid this behavior by synchronizing on the locking object prior to invoking this method.
- If an action is scheduled but has not started yet, it is guaranteed not to run.
- If no action is scheduled or executing, nothing changes.
-
isScheduled
public boolean isScheduled()Determine whether there is currently an outstanding scheduled action.- Returns:
- true if an action is pending
-
getScheduledTime
Get the scheduled time for the outstanding scheduled action, if any.- Returns:
- oustanding action scheduled time, or null if there is no scheduled action
-
schedule
Schedule the given action using the task scheduler passed to the constructor. Use of this method does not change the state of this instance.- Parameters:
action
- action to performinstant
- when to perform it- Returns:
- future for completion of
action
- Throws:
IllegalArgumentException
- if either parameter is nullRejectedExecutionException
- if the given task was not accepted for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
-