001: /*_############################################################################
002: _##
003: _## SNMP4J - TaskScheduler.java
004: _##
005: _## Copyright (C) 2003-2008 Frank Fock and Jochen Katz (SNMP4J.org)
006: _##
007: _## Licensed under the Apache License, Version 2.0 (the "License");
008: _## you may not use this file except in compliance with the License.
009: _## You may obtain a copy of the License at
010: _##
011: _## http://www.apache.org/licenses/LICENSE-2.0
012: _##
013: _## Unless required by applicable law or agreed to in writing, software
014: _## distributed under the License is distributed on an "AS IS" BASIS,
015: _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: _## See the License for the specific language governing permissions and
017: _## limitations under the License.
018: _##
019: _##########################################################################*/
020:
021: package org.snmp4j.util;
022:
023: import java.util.LinkedList;
024: import org.snmp4j.log.LogFactory;
025: import org.snmp4j.log.LogAdapter;
026:
027: /**
028: * The <code>TaskScheduler</code> uses a <code>ThreadPool</code> to recurrent
029: * execute <code>SchedulerTask</code>s.
030: *
031: * @author Frank Fock
032: * @version 1.6
033: * @since 1.6
034: */
035: public class TaskScheduler implements Runnable {
036:
037: private LogAdapter logger = LogFactory
038: .getLogger(TaskScheduler.class);
039:
040: private static final long DEFAULT_SCHEDULER_TIMEOUT = 5;
041:
042: private LinkedList tasks = new LinkedList();
043: private ThreadPool threadPool;
044: private boolean stop;
045: protected long schedulerTimeout = DEFAULT_SCHEDULER_TIMEOUT;
046:
047: /**
048: * Creates a <code>TaskScheduler</code> that uses the supplied
049: * <code>ThreadPool</code> to execute tasks.
050: *
051: * @param threadPool
052: * a <code>ThreadPool</code>.
053: */
054: public TaskScheduler(ThreadPool threadPool) {
055: this .threadPool = threadPool;
056: }
057:
058: /**
059: * Adds a task to the scheduler.
060: * @param task
061: * a <code>SchedulerTask</code>.
062: */
063: public synchronized void addTask(SchedulerTask task) {
064: tasks.addLast(task);
065: notify();
066: }
067:
068: /**
069: * Removes a task from the scheduler.
070: * @param task
071: * the <code>SchedulerTask</code> to be removed from the scheduler
072: * @return
073: * <code>true</code> if the task could be removed.
074: */
075: public synchronized boolean removeTask(SchedulerTask task) {
076: return tasks.remove(task);
077: }
078:
079: /**
080: * Removes all tasks.
081: */
082: public synchronized void clear() {
083: tasks.clear();
084: }
085:
086: /**
087: * Runs the scheduler. While in this method tasks are scheduled on the
088: * internal thread pool. The scheduler tries to schedule task fairly.
089: */
090: public void run() {
091: while (!stop) {
092: boolean readyToRun = false;
093: synchronized (this ) {
094: for (int i = 0; i < tasks.size(); i++) {
095: SchedulerTask task = (SchedulerTask) tasks.get(i);
096: if (task.isDone()) {
097: if (logger.isDebugEnabled()) {
098: logger.debug("Task '" + task + "' is done");
099: }
100: tasks.removeFirst();
101: continue;
102: } else if (task.isReadyToRun()) {
103: readyToRun = true;
104: while (!threadPool.tryToExecute(task)) {
105: try {
106: synchronized (threadPool) {
107: threadPool.wait(schedulerTimeout);
108: }
109: } catch (InterruptedException ex) {
110: logger
111: .warn("Scheduler interrupted, aborting...");
112: stop = true;
113: break;
114: }
115: }
116: tasks.addLast(tasks.removeFirst());
117: i--;
118: }
119: }
120: }
121: if (!readyToRun) {
122: try {
123: if (threadPool.isIdle()) {
124: synchronized (this ) {
125: wait(schedulerTimeout);
126: }
127: } else {
128: synchronized (threadPool) {
129: threadPool.wait(schedulerTimeout);
130: }
131: }
132: } catch (InterruptedException ex1) {
133: logger.warn("Scheduler interrupted, aborting...");
134: stop = true;
135: }
136: }
137: }
138: logger.info("Scheduler stopped.");
139: }
140:
141: /**
142: * Stops the schedulers run method.
143: * @param stop
144: * <code>true</code> to stop the scheduler.
145: */
146: public void setStop(boolean stop) {
147: this .stop = stop;
148: }
149:
150: /**
151: * Checks if the scheduler is (to be) stopped.
152: * @return
153: * <code>true</code> if the scheduler has been stopped or is being stopped.
154: */
155: public boolean isStop() {
156: return stop;
157: }
158: }
|