Asynchronous task execution with DelayQueue: postponing an already submitted task - java

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.

Related

how to repeat a task till certain time or till an answer has been received?

I want my ui thread to run an ansycTask (e.g. getting current Location)
However i want to limit it by time .how would you suggest doing this?
I have thought triggering a timer, but i'm not sure how.
in addition if i wanted to repeat an asyncTask that returns boolean value
and i want to give it 3 times retry chance.
how can i implement this?
I have thought about doing a few post with checking a static flag indicating an answer was received already, but i'm not sure this is the right way.
One way to ScheduledThreadPoolExecutor. This will allow you to run a thread at scheduled times. You can use methods scheduleWithFixedDelay to run your task at specified time.
Create your task by implementing Runnable. Use the Executor method scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit)
The executore will execute your task after the time you have specified. In your task, you can check for if the task is should retry or not. Once your conditions is satisfied or you have reached retries, you can cancel the task. You can use the shutdown method to end your task.
Simple class to accomplish this:
class RetryTask implements Runnable {
int retries = 3;
#Override
public void run() {
if(--retries == 0) {
//shutdown
}
if(location recieved) {
//shutdown
}
//else do your task
}
}

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

Synchronize periodic Task with another Thread

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.

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.

Getting the output of a Thread

What do you think is the best way for obtaining the results of the work of a thread? Imagine a Thread which does some calculations, how do you warn the main program the calculations are done?
You could poll every X milliseconds for some public variable called "job finished" or something by the way, but then you'll receive the results later than when they would be available... the main code would be losing time waiting for them. On the other hand, if you use a lower X, the CPU would be wasted polling so many times.
So, what do you do to be aware that the Thread, or some Threads, have finished their work?
Sorry if it looks similar to this other question, that's probably the reason for the eben answer, I suppose. What I meant was running lots of threads and know when all of them have finished, without polling them.
I was thinking more in the line of sharing the CPU load between multiple CPU's using batches of Threads, and know when a batch has finished. I suppose it can be done with Futures objects, but that blocking get method looks a lot like a hidden lock, not something I like.
Thanks everybody for your support. Although I also liked the answer by erickson, I think saua's the most complete, and the one I'll use in my own code.
Don't use low-level constructs such as threads, unless you absolutely need the power and flexibility.
You can use a ExecutorService such as the ThreadPoolExecutor to submit() Callables. This will return a Future object.
Using that Future object you can easily check if it's done and get the result (including a blocking get() if it's not yet done).
Those constructs will greatly simplify the most common threaded operations.
I'd like to clarify about the blocking get():
The idea is that you want to run some tasks (the Callables) that do some work (calculation, resource access, ...) where you don't need the result right now. You can just depend on the Executor to run your code whenever it wants (if it's a ThreadPoolExecutor then it will run whenever a free Thread is available). Then at some point in time you probably need the result of the calculation to continue. At this point you're supposed to call get(). If the task already ran at that point, then get() will just return the value immediately. If the task didn't complete, then the get() call will wait until the task is completed. This is usually desired since you can't continue without the tasks result anyway.
When you don't need the value to continue, but would like to know about it if it's already available (possibly to show something in the UI), then you can easily call isDone() and only call get() if that returns true).
You could create a lister interface that the main program implements wich is called by the worker once it has finished executing it's work.
That way you do not need to poll at all.
Here is an example interface:
/**
* Listener interface to implement to be called when work has
* finished.
*/
public interface WorkerListener {
public void workDone(WorkerThread thread);
}
Here is an example of the actual thread which does some work and notifies it's listeners:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Thread to perform work
*/
public class WorkerThread implements Runnable {
private List listeners = new ArrayList();
private List results;
public void run() {
// Do some long running work here
try {
// Sleep to simulate long running task
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
results = new ArrayList();
results.add("Result 1");
// Work done, notify listeners
notifyListeners();
}
private void notifyListeners() {
for (Iterator iter = listeners.iterator(); iter.hasNext();) {
WorkerListener listener = (WorkerListener) iter.next();
listener.workDone(this);
}
}
public void registerWorkerListener(WorkerListener listener) {
listeners.add(listener);
}
public List getResults() {
return results;
}
}
And finally, the main program which starts up a worker thread and registers a listener to be notified once the work is done:
import java.util.Iterator;
import java.util.List;
/**
* Class to simulate a main program
*/
public class MainProg {
public MainProg() {
WorkerThread worker = new WorkerThread();
// Register anonymous listener class
worker.registerWorkerListener(new WorkerListener() {
public void workDone(WorkerThread thread) {
System.out.println("Work done");
List results = thread.getResults();
for (Iterator iter = results.iterator(); iter.hasNext();) {
String result = (String) iter.next();
System.out.println(result);
}
}
});
// Start the worker thread
Thread thread = new Thread(worker);
thread.start();
System.out.println("Main program started");
}
public static void main(String[] args) {
MainProg prog = new MainProg();
}
}
Polling a.k.a busy waiting is not a good idea. As you mentioned, busy waiting wastes CPU cycles and can cause your application to appear unresponsive.
My Java is rough, but you want something like the following:
If one thread has to wait for the output of another thread you should make use of a condition variable.
final Lock lock = new ReentrantLock();
final Condition cv = lock.newCondition();
The thread interested in the output of the other threat should call cv.wait(). This will cause the current thread to block. When the worker thread is finished working, it should call cv.signal(). This will cause the blocked thread to become unblocked, allowing it to inspect the output of the worker thread.
As an alternative to the concurrency API as described by Saua (and if the main thread doesn't need to know when a worker thread finishes) you could use the publish/subscribe pattern.
In this scenario the child Thread/Runnable is given a listener that knows how to process the result and which is called back to when child Thread/Runnable completes.
Your scenario is still a little unclear.
If you are running a batch job, you may want to use invokeAll. This will block your main thread until all the tasks are complete. There is no "busy waiting" with this approach, where the main thread would waste CPU polling the isDone method of a Future. While this method returns a list of Futures, they are already "done". (There's also an overloaded version that can timeout before completion, which might be safer to use with some tasks.) This can be a lot cleaner than trying to gather up a bunch of Future objects yourself and trying to check their status or block on their get methods individually.
If this is an interactive application, with tasks sporadically spun off to be executed in the background, using a callback as suggested by nick.holt is a great approach. Here, you use the submit a Runnable. The run method invokes the callback with the result when it's been computed. With this approach, you may discard the Future returned by submit, unless you want to be able to cancel running tasks without shutting down the whole ExecutorService.
If you want to be able to cancel tasks or use the timeout capabilities, an important thing to remember is that tasks are canceled by calling interrupt on their thread. So, your task needs to check its interrupted status periodically and abort as needed.
Subclass Thread, and give your class a method that returns the result. When the method is called, if the result hasn't been created, yet, then join() with the Thread. When join() returns, your Thread's work will be done and the result should be available; return it.
Use this only if you actually need to fire off an asynchronous activity, do some work while you're waiting, and then obtain the result. Otherwise, what's the point of a Thread? You might as well just write a class that does the work and returns the result in the main thread.
Another approach would be a callback: have your constructor take an argument that implements an interface with a callback method that will be called when the result is computed. This will make the work completely asynchronous. But if you at all need to wait for the result at some point, I think you're still going to need to call join() from the main thread.
As noted by saua: use the constructs offered by java.util.concurrent. If you're stuck with a pre 1.5 (or 5.0) JRE, you ,might resort to kind of rolling your own, but you're still better of by using a backport: http://backport-jsr166.sourceforge.net/

Categories

Resources