Need an elegant way to invoke arbitrary code on a specified interval - java

Ok, I have a game server running in Java/Hibernate/Spring/Quartz. The game clock ticks with a Quartz timer, and that works just fine.
However, I have many other things that need to happen at specific, tweakable intervals (in game time, not real time).
For instance, every 24 hours game time (~ 47 minutes real time, depending on the servers clock multiplier) a bunch of different once-a-day game actions happen, like resupply, or what have you.
Now, the current system is pretty rough, but works - I have a table in the database that's essentially a cron - a string key, the execution time of the next event and then hours, minutes, seconds and days until the next one after that. The time ticker checks that and then fires off a message with that code (the events string key) in it to a queue, adding the days, minutes, seconds to the current time and setting that as the next execution time.
The message listener is the grody part - it switches on the key and hits one of its methods.
Now I understand that this can work just fine, but it really doesn't sit well with me. What would your solution be to this, to have each piece of code in its own little class? What design pattern covers this? (I'm sure there is one). I have a few ideas, but I'd like to hear some opinions.

Rather than a switching on a set of codes, you could use the code as a key into a map, where the values are objects that implement a handler interface. This allows you to be much more flexible in adding new event types.
The pattern looks something like this:
private final Map<String, Handler> handlers = new TreeMap<String, Handler>();
public void register(String event, Handler handler) {
handlers.put(event, handler);
}
public void handle(String event) {
Handler handler = handler.get(event);
if (handler == null) {
/* Log or throw an exception for unknown event type. */
}
else {
handler.execute();
}
}
Rather than explicitly registering handlers, you could use something like Java 6's ServiceLoader to add new behaviors just by dropping JARs into the class path.

I would use a variant of the Command Pattern. I would extend the Command pattern to make a IIntervalCommand class. It would have a interval property, and a readonly CanExecute property in addition to the Execute method.
Then you create a CommandList Class that holds a list of IIntervalCommands. It would have a method called CheckToExecute that you pass it the current game time. The CheckToExecute method would traverse the list calling CanExecute for each command. CanExecute will return true if the elapsed time has occurred. If CanExecute return true then CheckToExecute will call the Execute Method of the object implementing IIntervalCommand.
Then adding additional game events is a matter of creating a new class implementing IIntervalClass. Instantiating the Object and adding it to the IntervalCommandList.
If the processing of the event is time consuming then the command could spawn the processing as a separate thread. It will return false to it's CanExecute property until the thread returns even if the interval has passed again. Or you have it spawn off another thread if the interval passed again.
You avoid the giant case statement. You could eliminate the database and setup the parameters when you instantiate the objects. Or keep it and use it as part of a factory that creates all your IIntervalCommands.

Instead of switching on the key you can use a hashtable to dispatch these events. This way your timer events don't need to know about each other.
It should be possible do have something like:
timerQueue.registerHandler("key",new TimerHandler(){
// do something timer related
});
This way you can restart java code handling events without losing your persisted queue of events.
http://en.wikipedia.org/wiki/Priority_queue'>Priority queues are worth looking at if you have not already.

I personally wouldn't put this in the database but rather keep a separate service running in the background. Then my webservice or web application would communicate with this service through interprocess communication. Don't know how this translates into java world though.

Conceptually I think you're doing two things;
Firstly you have a scaled version of time. As long as the relationship between this time and wall-clock time remains constant I'm fairly sure I'd just delegate this scaling behavior to a single class, that would have signatures like
DateTime getFutureTime( VirtualTimeSpan timespan)
I'd be using this to map virtual time spans to instances of real-time. Thereafter you can operate in real-time, which probably simplifies things a little since you can the use standard scheduling features.
The second part regards scheduling work for a future worker process. There's a number of core technologies working with this; Conceptually I think JMS is the java-grand-dad of a lot of these, it defines concepts much like the ones you're using and what you need. I think taking a look at JMS is fine for seeing concepts you may find interesting, it uses selectors to send tasks to specific workers, much like the ones you decribe.
Alas, JMS never seemed to fit the bill for most people. A lot of people found it was too heavyweight or the implementations too buggy. So usually people ended up with home made queue technologies. But the concepts are all there. Can't you just use quartz ?

Related

How to timeout current running API call without using any extra threads?

I have been looking for answer to this from one week, couldn't find anything relatable. Finally decided to post here.
I have use-case, where I need to give custom timeouts to different API calls. This use-case sounds very common. right ? well, I want to achieve this without using any extra threads. I am looking for system-clock described as given below.
So basically, I want to write one method ( calling it, EnforceTimeout() ), This method takes callable ( API call converted into callable format, which returns response, or exception ), and timeout in Miliseconds.
public static Object EnforceTimeout(Callable callable, Long TimeoutInMS) throws exceptions {
// Do Some Steps on current thread, but not create new thread/thread-pool
// 1. Start the clock
// 2. Make API call
// 3. Clock runs in background which takes care of the timeout, and if API call exceeds the time-limit then automatically enforce the exception.
}
Now, Some of you might have doubt, how can we keep track of elapsed time, without creating new thread. So here, let me describe a strategy like an Event-loop( in JavaScript ). We can define a system-clock. This clock should be able to look after 10 to 100 such callable's timeouts. It can check on such callable on priority queue (whichever callable has closest ending time), whether we have crossed the time limit.
Your next argument would be, one such system-clock instance would be inefficient to manage large number of callables. In that case, We need system-clock-manager, which will manage, how many such a clocks we will need, it should be able to handle the scaling of such system clock instances.
Please, let me know, if anything as such possible in java. If my question/idea is duplicate, pls guide me to the discussion, where I can find more information about the same. Thank you very much.

Updating UI when variable changes

I have about 50 variables that get updated with an rate of about 1kHz by network, but their values change only every few seconds.
The values are for the UI (e.g. text, visibility and background color for buttons).
What is the most efficient way to update the UI?
I previously runned a task every 100ms on the UI thread that set all UI variables. The problem for me was the jitter of the other tasks every 100ms.
I'm looking for a solution to update the UI only when the variables changes.
Is there another way than implementing an own 'variable changed' listener?
That is a common problem in computer science and has been already solved by the Gang of Four. Use the Observer/Observable pattern to recognize changes. Android has also some built in modules that implement MVC (Adapters and ListViews...).
I believe that implementing a "variable changed" listener is probably the most correct (and most efficient) way to implement this, but you could always compare the value currently displayed in the UI to the value updated on the network prior to changing the UI.
if(!label.getText().equals(networkVal)) {
label.setText(networkVal);
}
I think something like that would work with the system that you described and reduce the jitter.
You might want to consider using setter methods for your variables and updating your widgets inside these methods.
I previously runned a task every 100ms on the UI thread that set all UI variables. The problem for me was the jitter of the other tasks every 100ms.
Then split the updating into ten parts and run every 10 ms one part.
From another answer:
you could always compare the value currently displayed in the UI to the value updated on the network prior to changing the UI.
I would not do it. This means to access the components often and getting their value may be expensive and complicated as they belong to the AWT-Thread. If your model contains an int, then getting the value back from the GUI may include parsing, which needlessly slows it down.
I keep the .getText().equals() in a normal thread.
This would work if this very thread was the only one updating the value. Which is not true as you should do all the updates on the AWT Thread. This could lead to problems.
The simple solution is:
Maintain a copy of the variables.
From time to time compare a few variables against the copy (so that in total every 100 ms all variables get checked).
When there are any differences, update the GUI (using SwingUtilities.invokeLater) and update the copy (normally).
The Observer Pattern is the nicer but much more verbose solution.
You can try to use either websocket or long polling.
What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet has a good discussion.

constantly check database [duplicate]

I'm using JDBC, need to constantly check the database against changing values.
What I have currently is an infinite loop running, inner loop iterating over a changing values, and each iteration checking against the database.
public void runInBG() { //this method called from another thread
while(true) {
while(els.hasElements()) {
Test el = (Test)els.next();
String sql = "SELECT * FROM Test WHERE id = '" + el.getId() + "'";
Record r = db.getTestRecord(sql);//this function makes connection, executeQuery etc...and return Record object with values
if(r != null) {
//do something
}
}
}
}
I'm think this isn't the best way.
The other way I'm thinking is the reverse, to keep iterating over the database.
UPDATE
Thank you for the feedback regarding timers, but I don't think it will solve my problem.
Once a change occurs in the database I need to process the results almost instantaneously against the changing values ("els" from the example code).
Even if the database does not change it still has to check constantly against the changing values.
UPDATE 2
OK, to anyone interested in the answer I believe I have the solution now. Basically the solution is NOT to use the database for this. Load in, update, add, etc... only whats needed from the database to memory.
That way you don't have to open and close the database constantly, you only deal with the database when you make a change to it, and reflect those changes back into memory and only deal with whatever is in memory at the time.
Sure this is more memory intensive but performance is absolute key here.
As to the periodic "timer" answers, I'm sorry but this is not right at all. Nobody has responded with a reason how the use of timers would solve this particular situation.
But thank you again for the feedback, it was still helpful nevertheless.
Another possibility would be using ScheduledThreadPoolExecutor.
You could implement a Runnable containing your logic and register it to the ScheduledExecutorService as follows:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.scheduleAtFixedRate(myRunnable, 0, 5, TimeUnit.SECONDS);
The code above, creates a ScheduledThreadPoolExecutor with 10 Threads in its pool, and would have a Runnable registered to it that will run in a 5 seconds period starting immediately.
To schedule your runnable you could use:
scheduleAtFixedRate
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
scheduleWithFixedDelay
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.
And here you can see the advantages of ThreadPoolExecutor, in order to see if it fits to your requirements. I advise this question: Java Timer vs ExecutorService? too in order to make a good decision.
Keeping the while(true) in the runInBG() is a bad idea. You better remove that. Instead you can have a Scheduler/Timer(use Timer & TimerTask) which would call the runInBG() periodically and check for the updates in the DB.
u could use a timer--->
Timer timer = new Timer("runInBG");
//Taking an instance of class contains your repeated method.
MyClass t = new MyClass();
timer.schedule(t, 0, 2000);
As you said in the comment above, if application controls the updates and inserts then you can create a framework which notifies for 'BG' thread or process about change in database. Notification can be over network via JMS or intra VM using observer pattern or both local and remote notifications.
You can have generic notification message like (it can be class for local notification or text message for remote notifications)
<Notification>
<Type>update/insert</Type>
<Entity>
<Name>Account/Customer</Name>
<Id>id</Id>
<Entity>
</Notification>
To avoid a 'busy loop', I would try to use triggers. H2 also supports a DatabaseEventListener API, that way you wouldn't have to create a trigger for each table.
This may not always work, for example if you use a remote connection.
UPDATE 2
OK, to anyone interested in the answer I believe I have the solution now. Basically the solution is NOT to use the database for this. Load in, update, add, etc... only whats needed from the database to memory. That way you don't have to open and close the database constantly, you only deal with the database when you make a change to it, and reflect those changes back into memory and only deal with whatever is in memory at the time. Sure this is more memory intensive but performance is absolute key here.

Should my custom events fire on GUI EDT or a "home-grown" EDT

I'm working on a project that does some intense math calculations (arrays of matrices, vectors, etc.), so naturally I'm splitting the work into jobs, and submitting them to a CompletionService to perform the work in parallel.
Each of the job objects can fire events to notify applications when the job starts, ends, progresses, and/or fails.
Currently, each of the jobs receive a handle to the entire list of event listeners, and simply iterate through, passing an event object to each one (in the same thread). This doesn't sit well with me, so I'd like to get other peoples' experience with doing this sort of thing with custom events/listeners.
Should I send my events to the GUI thread? Some of the listeners may or may not be GUI-related, and I'd like to not force users of my code to have to manually send their events onto the GUI thread, something like the following:
public class MyFooEventListener implements FooEventListener {
public void notifyJobStarted(FooEvent evt) {
// I want to avoid having users of my library write the following, right?
SwingUtilities.invokeLater(new Runnable(){
// update GUI here.
});
}
}
I wouldn't mind writing my own EventQueue, as this is for a research project in school, and I suppose it would be a good exercise in concurrency. Just trying to figure out what the "proper" way of implementing an event-driven system is, how to properly fire events, etc. Links to articles/tutorials and howtos are also greatly appreciated.
Thanks!
EDIT:
My event model has multiple event types, such as JobStartedEvent, JobEndedEvent, JobProgressEvent, etc. Is this a bad approach? Should I have a single event type, and if so, how do I pass information to the listeners that is not common to all events? Example: I want to pass a double in the range [0-1] for the progress event, but that is not applicable for an event like JobFailureEvent. What's the best approach to handling this?
I could put the extra information in the "source" object itself, but my source objects are the Job objects themselves, and it doesn't sit well with me to "leak" references to the job object, especially while it is running:
FooJob jobObject = (FooJob)event.getSource();
int progressPercent = jobObject.getCurrentProgress() * 100;
progressLabel.setText(progressPercent + "%");
No. Emit your events on whatever thread needs to raise them and leave it up to the users of your subsystem to decide how they wish to handle them. If they wish to message the results to a GUI, fine, if not, they can do whatever they want, eg. queue them to another thread. Just document 'Events are raised on an internal thread and event handlers must not block'.
Anything else puts constraints on users that they may well not want, as you say.
there are many ways to distribute events, each with their own pros and cons. if the consumer is not necessarily the GUI, then you definitely should not tie yourself to the awt EDT. unless you know for sure how the event consumers are going to work i would start simple and go from there. simple being: synchronously notify each consumer. if that ends up delaying the main task, then you should think about asynchronous notification. if the consumer is ultimately the GUI, then the consumer's notification method should be responsible for calling SwingUtilities.invokeLater.
Only threads that directly impact the GUI should be on the EDT. If you have other threads you need synchronized, just use the synchronized keyword (either on the method or on an object)
Spring has event handling and you can define custom events http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#context-functionality-events.

Java: a time-delayed queue that de-dupes

G'day everyone,
I have a system (the source) that needs to notify another system (the target) asynchronously whenever certain objects change. The twist is that the source system may mutate a single object many times in a short interval (updates are very "bursty"), and in that case it would be ideal to only notify the target system once, and with the final state of the object.
My thought was to use some kind of time-delayed, de-duping queue in front of a ThreadPoolExecutor for this. This queue would:
keep items on the queue for a minimum amount of time (ideally configured to be just a smidgin longer than the duration of a typical burst of mutations)
replace the existing object in the event that a duplicate (as defined by the object's identifier) is enqueued. The item should, however, retain its original place in the queue (to avoid any one item being perpetually bumped to the back of the queue - at some point we need to just send the notification even if another one will be coming along momentarily).
I haven't seen anything exactly like this in java.util, and my google-fu in this area appears to be particularly weak.
Has anyone implemented this before, know a BlockingQueue implementation that behaves this way, or have tips on how I might go about implementing one?
Thanks in advance!
Peter
PS. I know ESBs do this kind of thing, but that is too heavyweight an approach in this case - ideally I don't want to add any new library dependencies to the source system at all.
I think your best bet is to extend ArrayBlockingQueue and override offer and poll to add the time delay functionality.
Particularly ArrayBlockingQueue because it has a contains method.
Another idea is a DelayQueue where you override offer to remove the old element and insert the new but preserve the old time delay, which will essentially preserve order.
Then you need to wrap your queue items in a Delayed interface.
You could notify the system only that a change has occurred, and have the other system fetch the new state. Then don't notify of further changes until the state has been fetched.

Categories

Resources