Classes | Public Types | Public Member Functions

alma.acs.concurrent.ThreadLoopRunner Class Reference

List of all members.

Classes

class  CancelableRunnable
class  TaskWrapper

Public Types

enum  ScheduleDelayMode { FIXED_RATE, FIXED_DELAY }

Public Member Functions

 ThreadLoopRunner (Runnable task, long delayTime, TimeUnit unit, ThreadFactory tf, Logger logger)
long getDelayTimeMillis ()
synchronized boolean setDelayTime (long delayTime, TimeUnit unit)
ScheduleDelayMode getDelayMode ()
synchronized void setDelayMode (ScheduleDelayMode delayMode)
synchronized void runLoop ()
synchronized boolean isLoopRunning ()
boolean isTaskRunning ()
boolean isDisabled ()
synchronized void suspendLoop ()
synchronized boolean suspendLoopAndWait (long timeout, TimeUnit unit) throws InterruptedException
synchronized boolean shutdown (long timeout, TimeUnit unit) throws InterruptedException

Detailed Description

This class allows running some task repeatedly with a given delay. It is similar to the loop in C++ class ACS.Thread.

The code of the task to be executed gets passed to the constructor as a Runnable object. The time between executions is given in the constructor and can later be changed through setDelayTime(long, TimeUnit).

If the task takes some time to execute, you should consider implementing a soft cancel option. To do this, extend CancelableRunnable instead of simply implementing Runnable. When the action should be canceled (e.g. due to shutdown(long, TimeUnit)), the shouldTerminate flag will be set. Your code should check this flag at convenient times, and should return if the flag is set. Alternatively you can override the cancel method and terminate the task thread in different ways.

Method runLoop() starts the loop. Optionally the loop can be stopped with suspendLoop() or suspendLoopAndWait(long, TimeUnit), and can also be restarted with another call to runLoop(). To stop the loop for good, call shutdown(long, TimeUnit).

While the underlying classes from the JDK concurrent package could also be used directly, this class allows for shorter code that is also more similar to the style used in C++. Especially it imposes the limit of running one task repeatedly, which gives an easier API, at the expense of creating a separate instance of ThreadLoopRunner for some other repeated task. (The older JDK class java.util.Timer has problems recovering from errors and should not be used.)

Author:
hsommer

Member Enumeration Documentation

Enumerator:
FIXED_RATE 
FIXED_DELAY 

Constructor & Destructor Documentation

alma.acs.concurrent.ThreadLoopRunner.ThreadLoopRunner ( Runnable  task,
long  delayTime,
TimeUnit  unit,
ThreadFactory  tf,
Logger  logger 
)

Creates a ThreadLoopRunner that can repeatedly execute task. The mode defaults to ScheduleDelayMode#FIXED_RATE unless being changed via setDelayMode(ScheduleDelayMode).

Parameters:
task user-supplied Runnable, or better subtype ThreadLoopRunner.CancelableRunnable.
delayTime 
unit 
tf ThreadFactory from which the loop thread will be created.
logger Logger used by this class.

References alma.acs.concurrent.ThreadLoopRunner.setDelayTime().


Member Function Documentation

ScheduleDelayMode alma.acs.concurrent.ThreadLoopRunner.getDelayMode (  ) 
Returns:
The delay mode, either in use if the loop is already running, or to be used when calling runLoop().
long alma.acs.concurrent.ThreadLoopRunner.getDelayTimeMillis (  ) 
boolean alma.acs.concurrent.ThreadLoopRunner.isDisabled (  ) 

Returns true after shutdown(long, TimeUnit) was called. Then invoking any control method of this class will throw an IllegalStateException.

synchronized boolean alma.acs.concurrent.ThreadLoopRunner.isLoopRunning (  ) 
boolean alma.acs.concurrent.ThreadLoopRunner.isTaskRunning (  ) 
Returns:
true if the task is running, regardless of whether the loop is still running or has been stopped already.
See also:
suspendLoopAndWait(long, TimeUnit)

Referenced by alma.acs.concurrent.ThreadLoopRunner.runLoop().

synchronized void alma.acs.concurrent.ThreadLoopRunner.runLoop (  ) 

Runs the loop, either for the first time, or after a call to suspendLoop().

Exceptions:
IllegalStateException if the loop is already running, or if the run() method of a previous loop is still executing, or after shutdown
See also:
isLoopRunning()

References alma.acs.concurrent.ThreadLoopRunner.isLoopRunning(), and alma.acs.concurrent.ThreadLoopRunner.isTaskRunning().

Referenced by alma.acs.monitoring.blobber.BlobberImpl.execute(), alma.acs.concurrent.ThreadLoopRunner.setDelayTime(), alma.acs.alarmsystem.source.AlarmSourceImpl.start(), and alma.acs.alarmsystem.source.AlarmsMap.start().

synchronized void alma.acs.concurrent.ThreadLoopRunner.setDelayMode ( ScheduleDelayMode  delayMode  ) 

Sets the delay mode to be used for the next runLoop().

This method must not be called when the loop is already running (see isLoopRunning()), in which case it throws an IllegalStateException. The reason for this is that we see no need to change this mode on the fly, and rather avoid the overhead of automatically stopping and restarting the loop with the possible complications if the run() method does not terminate. Also we don't want getDelayMode() to give results that are not correct for the currently running loop. Note that the same issue is handled differently in setDelayTime(long, TimeUnit) where it seems desirable to change the delay time while the loop is running.

Parameters:
delayMode FIXED_RATE or FIXED_DELAY, see ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit) and ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit). Note that the C++ implementation uses equivalent of FIXED_RATE.
Exceptions:
IllegalStateException if called when the loop is running, or after shutdown.

References alma.acs.concurrent.ThreadLoopRunner.isLoopRunning().

Referenced by alma.acs.monitoring.blobber.BlobberImpl.execute(), alma.acs.alarmsystem.source.AlarmSourceImpl.start(), and alma.acs.alarmsystem.source.AlarmsMap.start().

synchronized boolean alma.acs.concurrent.ThreadLoopRunner.setDelayTime ( long  delayTime,
TimeUnit  unit 
)

Sets the time between calls to the loop action object, where the time for the task itself is included or not, depending on the set ScheduleDelayMode.

If this method is called while the thread loop is already running, it will wait for the current task to finish and then reschedule the actions at the new rate. If the currently running task fails to finish after 10 seconds, a warning is logged and false is returned.

Note that it is a limitation in the underlying ScheduledThreadPoolExecutor that the delay time cannot be changed without stopping and restarting the loop. If this becomes a problem, we could use the concurrent lib classes in a more customized way.

Parameters:
delayTime new delay time
unit 
See also:
setDelayMode(ScheduleDelayMode)

References alma.acs.concurrent.ThreadLoopRunner.isLoopRunning(), alma.acs.concurrent.ThreadLoopRunner.runLoop(), and alma.acs.concurrent.ThreadLoopRunner.suspendLoopAndWait().

Referenced by alma.acs.concurrent.ThreadLoopRunner.ThreadLoopRunner().

synchronized boolean alma.acs.concurrent.ThreadLoopRunner.shutdown ( long  timeout,
TimeUnit  unit 
) throws InterruptedException

Shuts down this thread loop runner, attempting to gracefully stop the running task if CancelableRunnable was provided, or otherwise letting the currently running loop action finish.

The ThreadLoopRunner cannot be used any more after this method has been called. (Then will return true, other methods will throw IllegalStateException.) The timeout refers to how long this method waits for the task to terminate. If it terminates before the given timeout, then true is returned, otherwise false which means that the Runnable action object is still in use and should not be reused later unless it is re-entrant.

Parameters:
timeout 
unit 
Returns:
true if loop action terminated before the given timeout, or if the loop was not running.
Exceptions:
InterruptedException 
IllegalStateException if called after shutdown.

Referenced by alma.acs.monitoring.blobber.BlobberImpl.cleanUp(), alma.acs.alarmsystem.source.AlarmsMap.shutdown(), and alma.acs.alarmsystem.source.AlarmSourceImpl.tearDown().

synchronized void alma.acs.concurrent.ThreadLoopRunner.suspendLoop (  ) 

Stops the loop, without attempting to cancel the possibly running action even if it was provided as a CancelableRunnable. Note also that this call returns quickly, without waiting for a possibly running action to finish.

The loop can be started again later via runLoop(). Suspending and restarting the loop does not lead to the creation of a new Thread.

Exceptions:
IllegalStateException if called after shutdown.
See also:
suspendLoopAndWait(long, TimeUnit)

Referenced by alma.acs.concurrent.ThreadLoopRunner.suspendLoopAndWait().

synchronized boolean alma.acs.concurrent.ThreadLoopRunner.suspendLoopAndWait ( long  timeout,
TimeUnit  unit 
) throws InterruptedException

Like suspendLoop(), but additionally waits for the currently running task (if any) to finish, with the given timeout applied.

If there is a task running and it fails to terminate, a subsequent call to runLoop() will fail with an IllegalStateException.

Parameters:
timeout 
unit 
Returns:
true if all went fine within the given time, otherwise false.
Exceptions:
InterruptedException if the calling thread is interrupted while waiting for the run method to finish.
IllegalStateException if called after shutdown.

References alma.acs.concurrent.ThreadLoopRunner.suspendLoop().

Referenced by alma.acs.concurrent.ThreadLoopRunner.setDelayTime().


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Enumerations Properties