org.jgroups.util.DefaultTimeScheduler Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.util;
import org.jgroups.Global;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import java.util.concurrent.*;
/**
* Implementation of {@link org.jgroups.util.TimeScheduler} by extending
* {@link java.util.concurrent.ScheduledThreadPoolExecutor} to keep tasks sorted. Tasks will get executed in order
* of execution time (by using a {@link java.util.concurrent.DelayQueue} internally.
*
* @author Bela Ban
*/
public class DefaultTimeScheduler extends ScheduledThreadPoolExecutor implements TimeScheduler {
/** How many core threads */
private static int TIMER_DEFAULT_NUM_THREADS=3;
protected static final Log log=LogFactory.getLog(DefaultTimeScheduler.class);
static {
String tmp;
try {
tmp=System.getProperty(Global.TIMER_NUM_THREADS);
if(tmp != null)
TIMER_DEFAULT_NUM_THREADS=Integer.parseInt(tmp);
}
catch(Exception e) {
log.error("could not set number of timer threads", e);
}
}
/**
* Create a scheduler that executes tasks in dynamically adjustable intervals
*/
public DefaultTimeScheduler() {
this(TIMER_DEFAULT_NUM_THREADS);
}
public DefaultTimeScheduler(ThreadFactory factory) {
this(factory, TIMER_DEFAULT_NUM_THREADS);
}
public DefaultTimeScheduler(ThreadFactory factory, int max_threads) {
super(max_threads, factory);
setRejectedExecutionHandler(new ShutdownRejectedExecutionHandler(getRejectedExecutionHandler()));
}
public DefaultTimeScheduler(int corePoolSize) {
super(corePoolSize);
setRejectedExecutionHandler(new ShutdownRejectedExecutionHandler(getRejectedExecutionHandler()));
}
public void setThreadFactory(ThreadFactory factory) {
super.setThreadFactory(factory);
}
public String dumpTimerTasks() {
return getQueue().toString();
}
public int getCurrentThreads() {
return super.getPoolSize();
}
public int getMinThreads() {
return super.getCorePoolSize();
}
public void setMinThreads(int size) {
super.setCorePoolSize(size);
}
public int getMaxThreads() {
return super.getMaximumPoolSize();
}
public void setMaxThreads(int size) {
super.setMaximumPoolSize(size);
}
public long getKeepAliveTime() {
return super.getKeepAliveTime(TimeUnit.MILLISECONDS);
}
public void setKeepAliveTime(long time) {
super.setKeepAliveTime(time, TimeUnit.MILLISECONDS);
}
/**
* Schedule a task for execution at varying intervals. After execution, the task will get rescheduled after
* {@link org.jgroups.util.DefaultTimeScheduler.Task#nextInterval()} milliseconds. The task is neve done until nextInterval()
* return a value <= 0 or the task is cancelled.
* @param task the task to execute
* @param relative scheduling scheme: true:
* Task is rescheduled relative to the last time it actually started execution
* false:
Task is scheduled relative to its last execution schedule. This has the effect
* that the time between two consecutive executions of the task remains the same.
* Note that relative is always true; we always schedule the next execution relative to the last *actual*
* (not scheduled) execution
*/
public Future> scheduleWithDynamicInterval(Task task) {
if(task == null)
throw new NullPointerException();
if (isShutdown())
return null;
TaskWrapper task_wrapper=new TaskWrapper(task);
task_wrapper.doSchedule(); // calls schedule() in ScheduledThreadPoolExecutor
return task_wrapper;
}
public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return super.scheduleWithFixedDelay(new RobustRunnable(command), initialDelay, delay, unit);
}
/**
* Answers the number of tasks currently in the queue.
* @return The number of tasks currently in the queue.
*/
public int size() {
return getQueue().size();
}
/**
* Stop the scheduler if it's running. Switch to stopped, if it's
* suspended. Clear the task queue, cancelling all un-executed tasks
*
* @throws InterruptedException if interrupted while waiting for thread
* to return
*/
public void stop() {
java.util.List tasks=shutdownNow();
for(Runnable task: tasks) {
if(task instanceof Future) {
Future future=(Future)task;
future.cancel(true);
}
}
getQueue().clear();
try {
awaitTermination(Global.THREADPOOL_SHUTDOWN_WAIT_TIME, TimeUnit.MILLISECONDS);
}
catch(InterruptedException e) {
}
}
public String toString() {
return getClass().getSimpleName();
}
/**
* Class which catches exceptions in run() - https://jira.jboss.org/jira/browse/JGRP-1062
*/
protected static class RobustRunnable implements Runnable {
final Runnable command;
public RobustRunnable(Runnable command) {
this.command=command;
}
public void run() {
if(command != null) {
try {
command.run();
}
catch(Throwable t) {
if(log.isErrorEnabled())
log.error("exception executing task " + command + ": " + t);
}
}
}
public String toString() {
return command != null? command.toString() : null;
}
}
protected class TaskWrapper implements Runnable, Future {
private final Task task;
private volatile Future> future; // cannot be null !
private volatile boolean cancelled=false;
public TaskWrapper(Task task) {
this.task=task;
}
public Future> getFuture() {
return future;
}
public void run() {
try {
if(cancelled) {
if(future != null)
future.cancel(true);
return;
}
if(future != null && future.isCancelled())
return;
task.run();
}
catch(Throwable t) {
log.error("failed running task " + task, t);
}
if(cancelled) {
if(future != null)
future.cancel(true);
return;
}
if(future != null && future.isCancelled())
return;
doSchedule();
}
public void doSchedule() {
long next_interval=task.nextInterval();
if(next_interval <= 0) {
if(log.isTraceEnabled())
log.trace("task will not get rescheduled as interval is " + next_interval);
}
else {
future=schedule(this, next_interval, TimeUnit.MILLISECONDS);
if(cancelled)
future.cancel(true);
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
boolean retval=!isDone();
cancelled=true;
if(future != null)
future.cancel(mayInterruptIfRunning);
return retval;
}
public boolean isCancelled() {
return cancelled;
}
public boolean isDone() {
return cancelled || (future == null || future.isDone());
}
public V get() throws InterruptedException, ExecutionException {
return null;
}
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy