Synchronize periodic Task with another Thread - java

I have the following situation in a Game i'm working:
class GameLogic implements Runnable
{
State state;
private State changeState()
{
//state changes here (note the `private`)
}
// this ticks at each 0.5 seconds
public void run()
{
//code that changes state
changeState();
}
// this will be called by a external Thread at any moment
public void update(Move move)
{
//code that changes state
applyMove(move);
}
private void applyMove(Move move)
{
//state changes here
//state = ... doesn't matter
}
}
The run method above is scheduled to execute at each 0.5 seconds, using a Timer or a ScheduledExecutorService.
The problem is the update method, will be called by another Thread at any moment. So i ask:
1 - What happens if a use synchronized to protect the state field? The timer will wait? How it will compensate for the 'waiting period'?
2 - Is there a better way of doing this? Maybe storing the moves on some queue?
Thanks!

Both Timer and ScheduledExecutorService can execute tasks at fixed rates or with fixed delays between executions. That means, a scheduled task with fixed rates will compensate the running time (including blocking time) of the execution. A scheduled task with fixed delays will not. See the documentation of the following methods for more information:
Fixed rate: Timer.scheduleAtFixedRate and ScheduledExecutorService.scheduleAtFixedRate
Fixed delay: Timer.schedule and ScheduledExecutorService.scheduleWithFixedDelay
There is always a better way. However, the solution looks fine. And as long as it works for you, go with it.

An additional way to deal with this problem is by having the updates coming in from the updating thread go to a Queue or something similar. This way, on each iteration of the state being adjusted you can grab all of the updates from the queue and apply them in the same thread.
Using this method, there would never be any conflict between the updating thread and the game loop thread.
Personally, I would use a while loop that takes advantage of some regulating mechanism instead of scheduling anything. You can use System.nanoTime() in order to apply your updates using time deltas. This would ensure that the execution of logic is not bound to the machine's performance.
There's a brilliant article on the topic here.

Related

Java Executor with throttling/throughput control

I'm looking for a Java Executor that allows me to specify throttling/throughput/pacing limitations, for example, no more than say 100 tasks can be processed in a second -- if more tasks get submitted they should get queued and executed later. The main purpose of this is to avoid running into limits when hitting foreign APIs or servers.
I'm wondering whether either base Java (which I doubt, because I checked) or somewhere else reliable (e.g. Apache Commons) provides this, or if I have to write my own. Preferably something lightweight. I don't mind writing it myself, but if there's a "standard" version out there somewhere I'd at least like to look at it first.
Take a look at guavas RateLimiter:
A rate limiter. Conceptually, a rate limiter distributes permits at a
configurable rate. Each acquire() blocks if necessary until a permit
is available, and then takes it. Once acquired, permits need not be
released. Rate limiters are often used to restrict the rate at which
some physical or logical resource is accessed. This is in contrast to
Semaphore which restricts the number of concurrent accesses instead of
the rate (note though that concurrency and rate are closely related,
e.g. see Little's Law).
Its threadsafe, but still #Beta. Might be worth a try anyway.
You would have to wrap each call to the Executor with respect to the rate limiter. For a more clean solution you could create some kind of wrapper for the ExecutorService.
From the javadoc:
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
void submitTasks(List<Runnable> tasks, Executor executor) {
for (Runnable task : tasks) {
rateLimiter.acquire(); // may wait
executor.execute(task);
}
}
The Java Executor doesn't offer such a limitation, only limitation by amount of threads, which is not what you are looking for.
In general the Executor is the wrong place to limit such actions anyway, it should be at the moment where the Thread tries to call the outside server. You can do this for example by having a limiting Semaphore that threads wait on before they submit their requests.
Calling Thread:
public void run() {
// ...
requestLimiter.acquire();
connection.send();
// ...
}
While at the same time you schedule a (single) secondary thread to periodically (like every 60 seconds) releases acquired resources:
public void run() {
// ...
requestLimiter.drainPermits(); // make sure not more than max are released by draining the Semaphore empty
requestLimiter.release(MAX_NUM_REQUESTS);
// ...
}
no more than say 100 tasks can be processed in a second -- if more
tasks get submitted they should get queued and executed later
You need to look into Executors.newFixedThreadPool(int limit). This will allow you to limit the number of threads that can be executed simultaneously. If you submit more than one thread, they will be queued and executed later.
ExecutorService threadPool = Executors.newFixedThreadPool(100);
Future<?> result1 = threadPool.submit(runnable1);
Future<?> result2 = threadPool.submit(runnable2);
Futurte<SomeClass> result3 = threadPool.submit(callable1);
...
Snippet above shows how you would work with an ExecutorService that allows no more than 100 threads to be executed simultaneously.
Update:
After going over the comments, here is what I have come up with (kinda stupid). How about manually keeping a track of threads that are to be executed ? How about storing them first in an ArrayList and then submitting them to the Executor based on how many threads have already been executed in the last one second.
So, lets say 200 tasks have been submitted into our maintained ArrayList, We can iterate and add 100 to the Executor. When a second passes, we can add few more threads based on how many have completed in theExecutor and so on
Depending on the scenario, and as suggested in one of the previous responses, the basic functionalities of a ThreadPoolExecutor may do the trick.
But if the threadpool is shared by multiple clients and you want to throttle, to restrict the usage of each one of them, making sure that one client won't use all the threads, then a BoundedExecutor will do the work.
More details can be found in the following example:
http://jcip.net/listings/BoundedExecutor.java
Personally I found this scenario quite interesting. In my case, I wanted to stress that the interesting phase to throttle is the consuming side one, as in classical Producer/Consumer concurrent theory. That's the opposite of some of the suggested answers before. This is, we don't want to block the submitting thread, but block the consuming threads based in a rate (tasks/second) policy. So, even if there are tasks ready in the queue, executing/consuming Threads may block waiting to meet the throtle policy.
That said, I think a good candidate would be the Executors.newScheduledThreadPool(int corePoolSize). This way you would need a simple queue in front of the executor (a simple LinkedBlockingQueue would suit), and then schedule a periodic task to pick actual tasks from the queue (ScheduledExecutorService.scheduleAtFixedRate). So, is not an straightforward solution, but it should perform goog enough if you try to throttle the consumers as discussed before.
Can limit it inside Runnable:
public static Runnable throttle (Runnable realRunner, long delay) {
Runnable throttleRunner = new Runnable() {
// whether is waiting to run
private boolean _isWaiting = false;
// target time to run realRunner
private long _timeToRun;
// specified delay time to wait
private long _delay = delay;
// Runnable that has the real task to run
private Runnable _realRunner = realRunner;
#Override
public void run() {
// current time
long now;
synchronized (this) {
// another thread is waiting, skip
if (_isWaiting) return;
now = System.currentTimeMillis();
// update time to run
// do not update it each time since
// you do not want to postpone it unlimited
_timeToRun = now+_delay;
// set waiting status
_isWaiting = true;
}
try {
Thread.sleep(_timeToRun-now);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// clear waiting status before run
_isWaiting = false;
// do the real task
_realRunner.run();
}
}};
return throttleRunner;
}
Take from JAVA Thread Debounce and Throttle

Asynchronous task execution with DelayQueue: postponing an already submitted task

I have a pool of threads dedicated to execute asynchronous tasks, using a shared DelayQueue.
Basicly, everything works well, except one thing: I would like to be able to postpone the execution of some already scheduled task.
For example, let's say that I submit now at time t=0 a task to execute in 30 seconds. After 10 seconds (t=10), I decide that, oh no, that task wont be executed at t=30 but at t=50; I have thus postponed it to 20 seconds later.
For that purpose, I have the postpone method, which modify the time set for the task and thus change the returned value of getDelay. The code is at the end of this post.
Infortunately, it doesn't work. It is actually very easy to break the system and do so that expired elements remain in the queue, much longer that they normally should.
More specifically, I observed the following unwanted behavior :
At time t=0, submit a first task to execute at t=30
At t=10, submit a second task to execute at t=20
At t=15, postpone the second task from t=20 to t=100
t=30 arrive, but the first task isn't executed, it stays in the queue. Its getDelay method now starts returning negative values.
t=40: the first task is already 10 seconds late, and still nothing happens. getDelay on the first task returns more and more smaller values as the time goes; the DelayQueue seems to be definitely mixed up.
t=90: perhaps an hope, because of the 30 seconds maximum poll time set in the q.poll call. In fact, no, I get a null and proceed to wait for the next task; my first task still stays in the queue with a negative delay.
t=100: hourra ! both tasks are executed right one after the other... the second one is on time, but the first one arrived finally 70 seconds late. This is unacceptable !
I also noticed that, if the task has never been the head while it was into the queue, I was able to postpone it safely, i.e. without disturbing other tasks.
So, my questions are :
Why it is so ? Am I doing something wrong in my code ?
Do I necessarily have to remove the task, then submit it again, to simulate a postpone ? Or is there another way to do it safely ? Am I really allowed to remove an object and then re-add that exact same object, or would it be preferable to submit another one to be sure to avoid all possible confusion ?
Bonus question: what is the complexity of the remove operation ? Presumabely O(n), if I assume that the queue is implemented as a kind of priority heap (it is impossible to make a binary search in a priority heap).
Thank you for your answers.
Here is the code. I have removed as much irrelevant parts as I can. I have especially deleted all exception handling.
public abstract class AbstractTaskExecutor<R extends Runnable> implements Runnable {
private final BlockingQueue<R> q;
...
public boolean submit (R dr) { return q.add(dr); }
public void run () {
while (!Thread.currentThread().isInterrupted()) {
Runnable r = q.poll(30, TimeUnit.SECONDS);
if (r!=null) r.run();
}}
}
public abstract class DelayedRunnable implements Runnable, Delayed {
private long time;
public DelayedRunnable (long l) {
time = System.currentTimeMillis() +l;
}
public final int compareTo (Delayed d) {
return (int)( Math.min(Math.max(Integer.MIN_VALUE, time - ((DelayedRunnable)d).time), Integer.MAX_VALUE) );
}
public final long getDelay (TimeUnit t) {
return t.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public final long getTime () { return time; }
public void postpone (long l) { time+=l; }
}
public class DelayedTaskExecutor extends AbstractTaskExecutor<DelayedRunnable> {
...
}
A question remains though: is it possible to reschedule the object that was just cancelled
Not if all you are doing is changing the time of "activation" You have to remove it, change it and add it back in as it is likely to be placed differently in the data structure. This is required as the structure determines the order of events and if you just change the value this may or may not lead to the order changing. You get similar problems if you change a key of Map after you add it. i.e. the structure does not behave correctly.
I would use a ScheduledExecutorService to wrap the delayed queue and thread pool.
When you place a delayed task you get back a Future object which you can cancel and reschedule as required.
At time t=0, submit a first task to execute at t=30
schedule a task for 30 later.
At t=10, submit a second task to execute at t=20
schedule a task for 10 later and save the Future.
At t=15, postpone the second task from t=20 to t=100
Future.cancel and reschedule
t=30 arrive, but the first task isn't executed, it stays in the queue. Its getDelay method now starts returning negative values.
In this example it would execute unless you had cancelled it.

Regarding stopwatch or timer or some other utility

I have a requirement to start a task..Now many threads can start this task and this task normally takes 4-5 seconds to complete. I want to prevent the starting of a task if this task has been already started by some other thread.
In order to implement this requirement, I am thinking of starting a timer or stopwatch in a different thread whenever the task is started by some thread. Now when the timer times out after a configured time-interval, another thread can starts a task.
So, is starting a timer or stopwatch in a different thread to see if the particular time has been reached is a good solution?Is there any good alternative for it?
If I understand correctly, this is a bad idea. Basically you are assumming your job will never run for more than 5 seconds so if the watch tells you that some job was started less than 5 seconds ago, you won't start another one. This is very unreliable.
Instead create some sort of flag that you set when job starts and unset when ends. AtomicBoolean is perfect for that:
private AtomicBoolean flag = new AtomicBoolean();
//...
if(!flag.getAndSet(true)) {
try {
//do your work
} finally {
flag.set(false);
}
} else {
//Already running
}
If you want another job to wait for the previous one instead of simply being discarded, just surround your task with synchronized or use some different locking mechanism.
Note: if your jobs are distributed you will need a distributed locking mechanism, like a databasse or hazelcast.
If you are trying to do this in java then you can consider using a synchronized block on the Object Oriented approach on JAVA.
So any task that you want to make sure is done by one thread at a time then make a class and a synchronized method in that class, also make sure you all the threads share the same object of the class and call this method in which they want to perform the task.
For Example
Class SyncTask{
synchronized void task1(){
//Perform your task here
}
}
Create the object of this class once during the lifetime of your application and then use this same object across all the threads and let them call this method to which you want to perform your task.
In the case of multiple threads invoking this method at the same time. JVM will take care of the sequence and if one thread is already performing a task, the others calling it will wait for the first one to finish.
In this way you will be sure that only on thread is performing the task at any given time.
I hope this helps.
If you want to schedule task the framework of choice is usually something similar to Quartz. It should allow you to do what you need and more. Regarding the issue of non running concurrent tasks, I would recommend you take a look at this previous SO post which should point you in the right direction.

How to ensure a Thread won't delay in Java?

I wrote a multi threading programme, which have two to four thread at the same time.
One of the thread is time critical thread, it will be called every 500 milliseconds, it is not allow to delay more than 10 milliseconds. But when other thread have more loading, I find that some delay, around two millisecond is occurred. (Print the timestamp to show it) So, I worry that after running for a long time it will delay more than 10 milliseconds, except from check the timestamp, and adjust the looping interval to make sure the time is not delay more than 10 milliseconds, is there any way to make it safe?
Thanks.
Sounds like you need Real-Time Java
If timing is critical, I use a busy wait on a core which is dedicated to that thread. This can give you << 10 micro-second jitter most of the time. Its a bit extreme and will result in the logical thread not being used for anything else.
This is the library I use. You can use it to reserve a logical thread or a whole core. https://github.com/peter-lawrey/Java-Thread-Affinity
By using isolcpus= in grub.conf on Linux you can ensure that the logical thread or core is not used for any else (except the 100 Hz timer and power management which are relatively small and < 2 us delay)
You can set your threads priorities:
myCriticalThread.setPriority(Thread.MAX_PRIORITY);
otherThread.setPriority(Thread.NORM_PRIORITY); // the default
yetAnotherThread.setPriority(Thread.MIN_PRIORITY);
It won't really guarantee anything though.
There is no guarantee that your thread isn't delayed, because the OS may decide to give other processes precedence (unless you put effort in setting up a complete real-time system including a modified OS). That being said, for basic tasks, you should use a ScheduledExecutorService like this:
class A {
private final ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
public void startCriticalAction(Runnable command) {
this.exe.scheduleAtFixedRate(command, 100, 100, TimeUnit.MILLISECONDS);
}
public void shutdown() {
this.exe.shutdown();
}
}
The executor service will do its best to execute the task every 100ms. You should not develop this functionality yourself, because a lot of things can go wrong.
Creep up on the timeout:
waitFor(int timeout)
{
dateTime wallTimeEnd;
wallTimeEnd=now()+(msToDateTime(timeout));
int interval=timeout/2;
while(true){
if(interval>10){
sleep(interval);
interval=dateTimeToMs(wallTimeEnd-now()) / 2;
}
else
{
do{
sleep(0);
interval=dateTimeToMs(wallTimeEnd-now());
}while(interval>0);
}
}
This only wastes a core for 5-10ms

Break out of a recursion in java when the time run out

I'm implementing AI for a chess-like game. I intend to use recursion to try all the possible state of the board and choose out the 'best move'.
Because of the time's limit per move, i need to have some mechanism to break out of those recursive procedure whenever the time limit is reached. Of course i can keep checking the time before making a recursion call and break out if the current time is near the limit, but it is a trade-off with the performance of my program.
It would be great if there is a way to break out of those recursive procedure whenever a timer end. However, since i'm new to Java, i don't know if there are any way to do so in java? Can you give an example code? :)
Checking the time, e.g. System.currentTimeMillis() costs about 200 ns per call. However if this is to much for you, you can have another thread set a flag to stop.
There is a mechanism to do this already.
ExecutorService es = Executors.newSingleThreadExecutor();
Future f = es.submit(new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
while(!Thread.interrupted()) {
// busy wait.
}
long time = System.nanoTime() - start;
System.out.printf("Finished task after %,d ns%n", time);
}
});
try {
f.get(1, TimeUnit.SECONDS); // stops if the task completes.
} catch (TimeoutException e) {
f.cancel(true);
}
es.shutdown();
prints
Finished task after 1,000,653,574 ns
Note: you don't need to start/stop the ExecutorService every time.
I don't think there is any nice way of doing this that doesn't involve checking if you can continue.
Even if you did check the time... what happens if you have 8 milliseconds remaining. Can you guarantee that your recursive call will finish in that time? Do you check the time after every little step (this may add a lot of extra overhead)?
One way is to have your execution(recursion) logic running in one thread, and a timer in another thread. When the timer completes, it invokes an interrupt() on your execution thread. In your worker thread, everytime you complete a recursion, you save the state that you need. Then if it gets interrupted, return the last saved state.
That's just a brief description of one way to do it.. by no means the best way
You can use a boolean flag to set when the AI task have to stop.
Create a thread that will run the AI task, this thread will check a boolean variable before each recursive call. To check boolean variable is more efficient than to call a method to get time. Do the parent thread sleep for the limited time. After it wake up, set the boolean flag to stop the child thread.

Categories

Resources