001: /* ScalableTimer.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Wed Dec 5 14:09:13 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.util;
020:
021: import java.util.Date;
022: import java.util.Timer;
023:
024: /**
025: * A facility for threads to schedule tasks for future execution in
026: * a background thread.
027: * It has the same function as {@link Timer}, but it is scalable by use of
028: * a collection of {@link Timer}. Use {@link ScalableTimer} if you want to
029: * schedule a lot of tasks.
030: * However, it doesn't support repeated execution.
031: *
032: * @author tomyeh
033: * @since 3.0.1
034: */
035: public class ScalableTimer {
036: private final ScalableTimerInfo[] _tis;
037: private int _threshold;
038:
039: /** Creates a scalable timer.
040: *
041: * <p>Note: no real timer (thread) is created until the first task
042: * being scheduled.
043: *
044: * @param cTimers the maximal allowed number of timers to use.
045: * 1 is assumed if nonpositive.
046: * @param threshold the threshold, i.e., the number of tasks allowed to
047: * be scheduled for a timer before creating additional timer.
048: * 1 is assumed if nonpositive.
049: * Note: if the number of scheduled task exceeds the capacity
050: * ({@link #getMaxTimerSize} * {@link #getThreshold}), the tasks are distributed evenly
051: * over all timers
052: */
053: public ScalableTimer(int cTimers, int threshold) {
054: if (cTimers <= 0)
055: cTimers = 1;
056: if (threshold <= 0)
057: threshold = 1;
058:
059: _tis = new ScalableTimerInfo[cTimers];
060: for (int j = cTimers; --j >= 0;)
061: _tis[j] = new ScalableTimerInfo();
062: _threshold = threshold;
063: }
064:
065: /** Returns the maximal allowed number of timers ({@link Timer})
066: * are used in this instance.
067: */
068: public int getMaxTimerSize() {
069: return _tis.length;
070: }
071:
072: /** Returns the threshold, i.e., the allowed number of tasks to be
073: * scheduled for a timer, before starting a new timer.
074: */
075: public int getThreshold() {
076: return _threshold;
077: }
078:
079: /** Terminates this timer, discarding any currently scheduled tasks.
080: * This method may be called repeatedly; the second and subsequent calls have no effect.
081: */
082: public void cancel() {
083: for (int j = _tis.length; --j >= 0;) {
084: final ScalableTimerInfo ti = _tis[j];
085: synchronized (ti) {
086: if (ti.timer != null) {
087: ti.timer.cancel();
088: ti.timer = null;
089: }
090: ti.count = 0;
091: }
092: }
093: }
094:
095: /** Schedules the specified task for execution after the specified delay.
096: * @param task task to be scheduled.
097: * @param delay delay in milliseconds before task is to be executed.
098: */
099: public void schedule(ScalableTimerTask task, long delay) {
100: getInfo(task).timer.schedule(task, delay);
101: }
102:
103: /** Schedules the specified task for execution at the specified time.
104: * @param task task to be scheduled.
105: * @param time time at which task is to be executed.
106: */
107: public void schedule(ScalableTimerTask task, Date time) {
108: getInfo(task).timer.schedule(task, time);
109: }
110:
111: private ScalableTimerInfo getInfo(ScalableTimerTask task) {
112: ScalableTimerInfo ti = null;
113: for (int j = _tis.length; --j >= 0;) {
114: if (_tis[j].count < _threshold) {
115: ti = _tis[j];
116: break; //found
117: }
118: if (ti == null || ti.count > _tis[j].count)
119: ti = _tis[j];
120: }
121:
122: synchronized (ti) {
123: ++ti.count;
124: if (ti.timer == null)
125: ti.timer = new Timer(true);
126: }
127: task.setScalableTimerInfo(ti);
128: return ti;
129: }
130: }
|