Here are some event managers I wrote in my spare time, these were inspired by Graham Edgecombe's implementation.
Code:
package net.exion.evt;
import java.util.LinkedList;
/**
* This is an implementation of single thread event processing, I wrote it for
* my server, Exion. Although it can be used for many functions. As of now this
* is no longer single threaded, there will be 2 threads, but will only activate
* the second thread if the time spent processing on the first thread exceeds
* the CYCLE_INTERVAL. I also decided to go with enforcing a set cycle
* interval, because the RuneScape client runs on a 600ms interval, it just
* wouldn't be right not to enforce this..
*
* @author Smokey`
*/
public class EventManager implements Runnable {
/**
* The time spent processing the events.
*/
public static long timeSpent = 0;
/**
* A controller, or hook if you will; to determine
* whether the event manager is running or not.
*/
private boolean running = true;
/**
* A linked list of events to execute; on a set interval
*/
private LinkedList<Event> events = new LinkedList<Event>();
/**
* The offload worker, or back-up thread. This will
* handle other events if the timeSpent is equal
* to or greater then the specified interval.
*/
private OffloadWorker offloadWorker = new OffloadWorker();
/**
* The current time before the events have been processed.
*/
private long startTime;
/**
* The interval at which to execute the events.
*/
final long CYCLE_INTERVAL = 600;
/**
* Another hook; (is) whether or not to offload
* events to the OffloadWorker
*/
private boolean offloadEvents = false;
/**
* Initialize the EventManager, start a new thread to process the events.
*/
public EventManager() {
new Thread(this).start();
}
/**
* Processes all the events in a syncrhonized fashion using a
* LinkedList. We'll set the startTime, process the events, and
* set the timeSpent then we'll sleep for the CYCLE_INTERVAL
* - timeSpent, This will ensure close to perfect timing every time.
* Note: I'm not sure if nano time would be better, seems like it would be,
* being such a tiny measurement of time.
*/
public void run() {
while (isRunning()) {
try {
//set the starting time
startTime = System.currentTimeMillis();
for (Event event : events) {
//execute the events
synchronized (event) {
event.execute();
}
}
//time spent = currentTime - startTime
timeSpent = System.currentTimeMillis() - startTime;
//Remove the last event and add it to the offload worker.
if (timeSpent >= CYCLE_INTERVAL
|| events.size() >= 10) {
events.remove(events.getLast());
//signal to offload new events being added
offloadEvents = true;
offloadWorker.thread.start();
}
Thread.sleep(CYCLE_INTERVAL - timeSpent);
} catch (Exception ex) {
ex.printStackTrace();
destruct();
return;
}
}
}
/**
* Add an event to either the OffloadWorker or this
* thread.
*
* @param evt the event to be added
*/
public void put(Event evt) {
if(offloadEvents) {
offloadWorker.events.add(evt);
} else
events.add(evt);
}
/**
* Stops an event from being executed.
*
* @param evt the event to be halted from execution
*/
public void halt(Event evt) {
synchronized (events) {
if(!events.remove(evt)){
offloadWorker.events.remove(evt);
}
}
}
/**
* @return whether or not the event manager is running
*/
public boolean isRunning() {
return running;
}
/**
* Stop all events.
*/
public void destruct() {
running = false;
events = null;
}
/**
* Gets the instance of this class.
*
* @return the instance
*/
public static EventManager getInstance() {
return InstanceHolder.instance;
}
/**
* Instance holder for this class
*/
static class InstanceHolder {
public static final EventManager instance = new EventManager();
}
}
Code:
package net.exion.evt;
import java.util.LinkedList;
/**
* A back up thread, to handle excess events when
* the EventManager is being over used; basicly
* just a way to handle huge loads.
*
* @author Smokey`
*/
public class OffloadWorker implements Runnable {
/**
* A linked list of events to execute.
*/
public LinkedList<Event> events = new LinkedList<Event>();
/**
* Thread for the OffloadWorker
*/
public Thread thread = null;
/**
* Initialize the thread.
*/
public OffloadWorker() {
thread = new Thread(this);
}
/**
* Execute all off-loaded events on the given interval.
*/
@Override
public void run() {
while (true) {
long startTime = System.currentTimeMillis();
try {
for(Event event : events) {
synchronized(event) {
event.execute();
}
}
Thread.sleep(EventManager.getInstance().CYCLE_INTERVAL
- (System.currentTimeMillis() - startTime));
} catch (Exception ex) {
ex.printStackTrace();
return;
}
}
}
}
Code:
package net.exion.evt;
/**
* Represents an event to be executed.
*
* @author Smokey`
*/
public abstract class Event {
/**
* Being called on a set interval
*/
public abstract void execute();
}
This is 100% my code, I will give credits though.
Credits:
- Daniel(GhostSnyper) - Discussion/Ideas
- Impulser' - Discussion/Ideas
- Graham - Inspiration
The reason I wrote this is simple. I didn't want to be dependant on someone elses code, mainly Graham's. So I wrote this for my server.
I'm open to new ideas/discussion.
Also, I DIDN'T KNOW WHERE TO POST THIS.. SO IT'S HERE..
~Smokey`