All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.util.DefaultTimeScheduler Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version

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