Increment sleep/wait time until required - java

I'm not very good in multi-threading, this might be a basic question. But i have'nt been able to find an answer.
Scenario:
Lets say I have an event listener which is fired by something. Every time the event is fired, i want to start a new thread which takes about 3 seconds to execute.
Problem:
The problem is that the event can be fired more than once in a second, and I don't want to start multiple threads at once.
Requirement:
How can I schedule a thread lets say at 1000ms after the event. If the event keeps on firing, i want to keep delaying the scheduled time of thread. This way my thread executes after 1000ms of the last time the event was fired.

The event listener, on start up, creates and starts a new private thread. The thread contain a list of tasks to do and executes them one at a time sequentially. Each time the even listener receives a new event, it creates a new task, and adds it to the list of tasks in the private thread.
EDIT: Eugene suggested using a Thread Pool, which might be beneficial in your case if you have a great amount of work to do with each task taking up considerable amount of time. Take a look at thread pools in Java API, like this: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

I would use a ScheduledExecutorService - schedule the task to happen in one second and if there is a task already scheduled cancel it and schedule a new one to happen in one second
This way your task will execute one second after the last time the event was triggered.
private class Task implements Runnable {
#Override
public void run() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private Future<?> scheduledTaskHandle;
private class Listener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (scheduledTaskHandle != null && !scheduledTaskHandle.isDone()) {
scheduledTaskHandle.cancel(false);
}
scheduledTaskHandle = executorService.schedule(new Task(), 1, TimeUnit.SECONDS);
}
}
The Task is a Runnable that does your long-running operation. the Listener is your listener class.
In the Listener.actionPerformed method we first check whether a task is already scheduled by using the Future, if it is we cancel it. We don't need to worry about race hazards here is if the tasks finishes in between the call to isDone and the call to cancel then nothing will happen.
If the task is running at the point when the Listener fires then that task will complete, as the cancel method is called with false. Another task will be scheduled to run one second after the firing of the listener or once the currently running task has completed (as we are only using a single thread no more than one task can run).
The Listener will then schedule a new execution of the task to happen in one second.

Related

How to remove a task from ScheduledExecutorService?

I have a ScheduledExecutorService that times a few different task periodically with scheduleAtFixedRate(Runnable, INIT_DELAY, ACTION_DELAY, TimeUnit.SECONDS);
I also have a different Runnable that I'm using with this scheduler.
the problem starts when I want to remove one of the tasks from the scheduler.
Is there a way to do this?
Am I doing the right thing using one scheduler for different tasks?
What is the best way to implement this?
Simply cancel the future returned by scheduledAtFixedRate():
// Create the scheduler
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Create the task to execute
Runnable r = new Runnable() {
#Override
public void run() {
System.out.println("Hello");
}
};
// Schedule the task such that it will be executed every second
ScheduledFuture<?> scheduledFuture =
scheduledExecutorService.scheduleAtFixedRate(r, 1L, 1L, TimeUnit.SECONDS);
// Wait 5 seconds
Thread.sleep(5000L);
// Cancel the task
scheduledFuture.cancel(false);
Another thing to note is that cancel does not remove the task from scheduler. All it ensures is that isDone method always return true. This may lead to memory leaks if you keep adding such tasks. For e.g.: if you start a task based on some client activity or UI button click, repeat it n-times and exit. If that button is clicked too many times, you might end up with big pool of threads that cannot be garbage collected as scheduler still has a reference.
You may want to use setRemoveOnCancelPolicy(true) in ScheduledThreadPoolExecutor class available in Java 7 onwards. For backward compatibility, default is set to false.
If your ScheduledExecutorService instance extends ThreadPoolExecutor (e.g. ScheduledThreadPoolExecutor), you could use remove(Runnable) (but see the note in its javadoc: "It may fail to remove tasks that have been converted into other forms before being placed on the internal queue.") or purge().

How to modify this example code in order to show the differences between the three methods for updating the UI in BlackBerry

I'm triying to understand the differences between the three methods for managing the UI interactions.
I'm really confused with these three terms when triying to figure them out in a real case.
The below code shows the function of the invokeAndWait method, but if I replace it by
invokeLater or getEventLock() the program will work exactly the same way.
Could someone please modify the code in order to show the differences between the three
methods for updating the UI?
public final class HelloWorldMainScreen extends MainScreen
{
private LabelField labelField;
public HelloWorldMainScreen()
{
labelField = new LabelField("Hello World");
add(labelField);
MainScreenUpdaterThread thread = new MainScreenUpdaterThread(this);
thread.start();
}
public void appendLabelText(String text){
labelField.setText(labelField.getText()+"\n"+text);
}
}
public class MainScreenUpdaterThread extends Thread {
HelloWorldMainScreen mainScreen;
public MainScreenUpdaterThread(HelloWorldMainScreen mainScreen){
this.mainScreen = mainScreen;
}
public void run(){
for (int i = 0; i < 10; i++) {
try{
Thread.sleep(5000);
}catch(InterruptedException ex){};
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
mainScreen.appendLabelText("Update");
}
});
}
}
}
These three concepts are very confusing for many starting people so any explanatory source code
describing their functions will be strongly helpful for anybody, I think.
Thanks in advance!
My understanding for three different approaches:
Application.getEventLock() - get event lock as soon as possible
UiApplication.invokeLater() - put Runnable into event queue and it will be executed after all other tasks that were put before to this queue
UiApplication.invokeAndWait() - same as previous one except calling thread will be stopped until Runnable will be run
My personal opinion never use first method. I don't think that any of my draw or UI changes tasks are more prioritized that other tasks already put to event queue.
I use mostly second method and I used once last one when I implemented some modal popup dialog selection.
getEventLock() :Retrieves the application user interface event lock.
Worker threads should synchronize on this thread if they wish to execute code serialized with the event thread. Your worker thread should hold the lock only for a short period of time, as this action pauses the thread dispatcher.
Any operation involving the device's user interface must be done with the lock held. The UI system also guarantees that any methods it invokes will execute on a thread that already has the lock.
An application should never call notify or wait on this object.
invokeLater(): Puts runnable object into this application's event queue.
Invoke this method, passing a runnable object, to have that object's run() method invoked on the dispatch thread, after all pending events are processed.
If there is no event dispatch thread (ie. hasEventThread() returns false), then the last item to be queued is dropped when the queue surpasses its size limit. Note: If an application does not have an event thread, you may invoke setAcceptEvents(boolean) to inform the runtime system that the application no longer accepts events. All events queued to that application are then discarded.
invokeAndWait(): Puts runnable object into this application's event queue, and waits until it is processed.
Invoke this method, passing a runnable object, to have that object's run() method invoked on the dispatch thread, after all pending events are processed.
This method blocks until the insert event is processed (that is, until the runnable object's run() method returns).
It is safe to call this method on the event dispatch thread. In this case the runnable will be executed immediately.
If there is no event dispatch thread (ie. hasEventThread() returns false), then the last item to be queued is dropped when the queue surpasses its size limit. Note: If an application does not have an event thread, you may invoke setAcceptEvents(boolean) to inform the runtime system that the application no longer accepts events. All events queued to that application are then discarded.
API documentation: http://www.blackberry.com/developers/docs/4.3.0api/net/rim/device/api/system/Application.html#invokeLater(java.lang.Runnable)

Schedule a single-threaded repeating runnable in java, but skip the current run if previous run is not finished

Sometimes the duration of a repeated task is longer than its period (In my case, this can happen for hours at a time). Think of a repeated task that takes 7 minutes to run and is scheduled to run every 10 minutes, but sometimes takes 15 minutes for each run for a few hours in a row.
The Timer and ScheduledThreadPoolExecutor classes both have a scheduleAtFixedRate method that is usually used for this type of functionality. However, both have the characteristic that they 'try to catch up when they fall behind'. In other words, if a Timer falls behind by a few executions, it builds up a queue of work that will be worked on continuously until it catches back up to the number of runs that would have happened if none of the tasks had taken longer than the specified period. I want to avoid this behavior by skipping the current execution if the previous run is not complete.
I have one solution that involves messing around with the afterExecution method of a pooled executor, recalculating a delay, and rescheduling the runnable with the new delay, but was wondering if there's a simpler way, or if this functionality already exists in a common library somewhere. I know about scheduling with a fixed delay rather than a fixed period, but this will not work for me since it's important to try to execute the tasks at their fixed times. Are there any simpler options than my afterExecution solution?
I think what you want is for the long-running task itself to not run in the ScheduledExecutorService itself, but in a background thread. Then the fixed-rate task will always complete quickly, since it is only used for checking whether to start the actual task in the background (or not, if it's still running from last time).
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
final Runnable actualTask = null;
executorService.scheduleAtFixedRate(new Runnable() {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<?> lastExecution;
#Override
public void run() {
if (lastExecution != null && !lastExecution.isDone()) {
return;
}
lastExecution = executor.submit(actualTask);
}
}, 10, 10, TimeUnit.MINUTES);
You could use scheduleWithFixedDelay method instead. It's similar but this one does not have a queue for missed runs and instead starts counting again only when the current Runnable was terminated.
The documentation states the reexecution of the Runnable will be scheduled based on the delay parameter:
The delay between the termination of one execution and the commencement of the next.
Make a third class, say called Coordinator. Coordinator has a synchronized startRunning() method which sets isRunning to true and returns true if another thread was not running already. There should also be a synchronized stopRunning method which sets isRunning to false. It returns true if a runnable is already running. You make a single instance of this class and pass a reference to all of the runnables you construct. In the runnable's run method you first call startRunning and check the return to verify that another one isn't running already. Make sure to put the code in run() in a try-finally and call stopRunning from within the finally block.

How to stop immediately the task scheduled in Java.util.Timer class

I tried everything. This one too How to stop the task scheduled in Java.util.Timer class
I have one task that implements java.util.TimerTask
I call that task in 2 ways:
I schedule Timer like this:
timer.schedule(timerTask, 60 * 1000);
sometimes I need that work to start immediately and it has to cancel timerTask if there is any that is working
cancelCurrentWork();
timer.schedule(timerTask, 0);
This implementation doesn't stop current work:
(documentation says: If the task is running when this call occurs, the task will run to completion, but will never run again)
But I need it to stop.
public static void cancelCurrentwork() {
if (timerTask!= null) {
timerTask.cancel();
}
}
This implementation just cancels the timer but leaves currently doing task to be finished.
public static void cancelCurrentwork() {
if (timer!= null) {
timer.cancel();
}
}
Is there a way in timer to STOP current executing taks, something like Thread.kill() or something? When I need that task to stop I want it to loose all its data.
There is no way for the Timer to stop the task in its tracks.
You will need to have a separate mechanism in the running task itself, that checks if it should keep running. You could for instance have an AtomicBoolean keepRunning variable which you set to false when you want the task to terminate.
if your timer is using some sort of file/socket etc, you can close that object from outside the timer, and the timer task will throw an exception, and you can use it to stop the timer.
but in general you need some sort of poison pill to successfully stop a separate thread/timer.

Executing SwingWorker from SwingWorker - waits until first one stops

I'm trying to execute a SwingWorker (SubWorker) from another SwingWorker (MainWorker), and then I want the MainWorker to wait for the SubWorker to complete. In the mean time, the MainWorker should update itself according to property changes of the SubWorker.
public class MainWorker extends SwingWorker<Void,Void>
{
public Void doInBackground()
{
SubWorker sw = new SubWorker();
sw.execute();
try {
network.get(); // wait for completion
} catch (Exception ex) {
}
return null;
}
}
The problem is that the SubWorker's doInBackground method is not called until the MainWorker has finished, while the MainWorker is waiting for the SubWorker to finish.
How can I let the SubWorker run parallel to the MainWorker's activities?
If you have only one sub-worker, I'm not sure what is the point - why can't you just execute the task in the SW body?
If you have multiple parallel sub-tasks, and you want to group them and report on their progress, you don't really need separate SwingWorkers - just start threads or use an executor to schedule the tasks. If you want to publish interim results, pass a blocking queue to the tasks, where they would push the updates.
The main (or rather the only) SwingWorker would take items from that queue and update the GUI using the publish()/process() methods. When a subtask finishes work, it can push special token in the queue (or null). That's how you can keep track of the outstanding subtasks and decide when to terminate the loop.
Alternatively, if you have a bunch of self-contained tasks you can use CompletionService and update the status in similar way from the SW.

Categories