
delight.concurrency.schedule.ScheduleInIntervals Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of delight-concurrency Show documentation
Show all versions of delight-concurrency Show documentation
An abstract and lightweight definition of concurrency fundamentals.
The newest version!
package delight.concurrency.schedule;
import delight.concurrency.Concurrency;
import delight.concurrency.wrappers.SimpleTimer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Enables to schedule items in a fixed number of intervals.
*
* @author mroh004
*
* @param
*/
public class ScheduleInIntervals {
public interface ScheduleEventListener {
public void onUnpaused();
public void onProcessed();
}
public interface ScheduledListener {
public void process(List toProcess);
}
public final static int[] INTERVALS = new int[] { 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 3000,
4000, 5000, 6000, 7000, 8000, 9000, 10000, 15000, 20000, 30000, 40000, 50000, 60000, 80000, 100000,
60 * 60 * 1000, 24 * 60 * 60 * 1000 };
private final ScheduledListener listener;
private SimpleTimer timer;
private final Concurrency con;
@SuppressWarnings("rawtypes")
private final Map scheduledItems;
private final Set pausedItems;
private final List toProcess;
private final List scheduleEventListeners;
private volatile int counter;
private volatile boolean globalPaused;
public void stop() {
if (timer != null) {
globalPaused = false;
toProcess.clear();
timer.stop();
timer = null;
}
}
private boolean validInterval(final int interval) {
for (final int testInt : INTERVALS) {
if (testInt == interval) {
return true;
}
}
return false;
}
/**
* Prevents this scheduler from triggering new processes temporarily.
*
*/
public void pause() {
globalPaused = true;
}
public void unpause() {
globalPaused = false;
for (final ScheduleEventListener listener : scheduleEventListenersCopy()) {
listener.onUnpaused();
}
}
private final List scheduleEventListenersCopy() {
return new ArrayList(scheduleEventListeners);
}
public boolean isPaused() {
return globalPaused || pausedItems.size() > 0;
}
public boolean processingPending(final ItemType item) {
return toProcess.contains(item);
}
public boolean processingPending() {
return toProcess.size() > 0;
}
public void addScheduleEventListener(final ScheduleEventListener listener) {
assert !this.scheduleEventListeners.contains(listener);
this.scheduleEventListeners.add(listener);
}
public void removeScheduleEventListener(final ScheduleEventListener listener) {
assert this.scheduleEventListeners.contains(listener);
this.scheduleEventListeners.remove(listener);
}
@SuppressWarnings("unchecked")
public void scheduleAt(final int interval, final ItemType item) {
if (!validInterval(interval)) {
throw new IllegalArgumentException(
"Interval [" + interval + "] not allowed. Only use one of [" + INTERVALS + "]");
}
scheduledItems.get(interval).add(item);
if (timer == null) {
startTimer();
}
}
public void pause(final int interval, final ItemType item) {
assert !this.pausedItems.contains(item);
this.pausedItems.add(item);
}
public void unpause(final int interval, final ItemType item) {
assert this.pausedItems.contains(item);
this.pausedItems.remove(item);
for (final ScheduleEventListener listener : scheduleEventListenersCopy()) {
listener.onUnpaused();
}
}
public void unscheduleAt(final int interval, final ItemType item) {
if (!validInterval(interval)) {
throw new IllegalArgumentException(
"Interval [" + interval + "] not allowed. Only use one of [" + INTERVALS + "]");
}
assert scheduledItems.get(interval).contains(item) : "Item cannot be removed since it was not scheduled.\n"
+ " Item: [" + item + "]\n" + " At interval: [" + interval + "]" + " Registered Items: ["
+ scheduledItems + "]";
scheduledItems.get(interval).remove(item);
toProcess.remove(item);
if (scheduledItemCount() == 0) {
stop();
}
}
@SuppressWarnings("rawtypes")
public boolean isScheduled(final ItemType item) {
for (final Entry e : scheduledItems.entrySet()) {
if (e.getValue().contains(item)) {
return true;
}
}
return false;
}
public void unscheduleAll(final ItemType item) {
for (final int intervall : INTERVALS) {
unscheduleAt(intervall, item);
}
assert scheduledItemCount() == 0;
stop();
}
/**
* How many items are scheduled in total.
*
* @return
*/
public int scheduledItemCount() {
int count = 0;
for (final int interval : INTERVALS) {
count = count + scheduledItems.get(interval).size();
}
return count;
}
@SuppressWarnings("unchecked")
protected void tick() {
counter += 200;
if (counter > INTERVALS[INTERVALS.length - 1]) {
counter = 200;
}
final List toProcessAdd = new ArrayList();
for (final int interval : INTERVALS) {
if (counter % interval == 0) {
toProcessAdd.addAll(scheduledItems.get(interval));
}
}
for (final ItemType toProcessItem : toProcessAdd) {
if (!toProcess.contains(toProcessItem)) {
toProcess.add(toProcessItem);
}
}
if (!this.globalPaused) {
this.listener.process(filterActive(toProcess));
toProcess.clear();
for (final ScheduleEventListener listener : scheduleEventListenersCopy()) {
listener.onProcessed();
}
}
}
private final List filterActive(final List items) {
final List activeItems = new ArrayList(items.size());
for (final ItemType item : items) {
if (isScheduled(item) && !pausedItems.contains(item)) {
activeItems.add(item);
}
}
return activeItems;
}
protected void startTimer() {
assert this.timer == null;
this.timer = con.newTimer().scheduleRepeating(1, 200, new Runnable() {
@Override
public void run() {
tick();
}
});
}
public ScheduleInIntervals(final Class itemType, final Concurrency con,
final ScheduledListener listener) {
super();
this.listener = listener;
this.scheduledItems = con.newCollection().newThreadSafeMap(Integer.class, List.class);
this.toProcess = con.newCollection().newThreadSafeList(itemType);
for (final int interval : INTERVALS) {
this.scheduledItems.put(interval, con.newCollection().newThreadSafeList(itemType));
}
this.con = con;
this.counter = 0;
this.globalPaused = false;
this.pausedItems = con.newCollection().newThreadSafeSet(itemType);
this.scheduleEventListeners = con.newCollection().newThreadSafeList(ScheduleEventListener.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy