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

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.

Related

Java.util.Timer - Process continue when main thread end

I have this simple code using util.Timer
public class CheckDBAccessListOpenAccesses extends TimerTask {
public static void main(String[] args) {
CheckDBAccessListOpenAccesses object = new CheckDBAccessListOpenAccesses();
}
private CheckDBAccessListOpenAccesses() {
System.out.println("Start");
Timer whatAccessAreOpen = new Timer();
whatAccessAreOpen.scheduleAtFixedRate(this, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1));
Thread.sleep(100*60*1000);
System.out.println("finish");
}
#Override
public void run() {
System.out.println("one minute");
}
}
When I run the code, the process runs forever.
I want the process to stop when the main Thread ends. Why is the Timer keeps the process alive? is there a way to prevent it?
Java has two types of Threads: user threads and daemon threads. User threads prevent the JVM from terminating, daemon threads do not. By default, a Timer is backed by a user thread, unless it is specified to run as a daemon in the constructor.
To prevent the Timer from keeping the process alive, instantiate the Timer with:
new Timer (true)
See: https://docs.oracle.com/javase/8/docs/api/java/util/Timer.html#Timer-boolean-
Well, that's in the Timer's API.
The Timer#scheduleAtFixedRate method:
Schedules the specified task for repeated fixed-rate execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
[...]
You may want to use Timer#schedule for one-shot operations, instead.
Otherwise, and what you likely really want, is to have the Timer object visible from your main thread, so you can just invoke Timer#cancel on it when you wish to cancel the scheduled operation, e.g. when your main thread terminates.

repetitve timer doesnt work when looper is inside the runnable

I am testing a few things with TimerTask and Timers and android , and i noticed that if i put Looper inside the run () method, the TimerTask runs just once, even though i defined it to be repetitive.Any ideas why is that ?
here is the MainActivity part
Timer timi=new Timer();
timi.scheduleAtFixedRate(new locac(nok,this),10, 1000);
and here is the worker timerTask class
public void run ()
{
Looper.prepare();
int loto=23;
int lato=23;
long time=1220227200;
String test=String.valueOf(lato);
String test3=String.valueOf(loto);
String test1=String.valueOf(time);
dbadapter mkola=new dbadapter(Ctx);
mkola.openToWrite();
mkola.insert(test,test1,test3);
Looper.loop();
}
as soon as i remove the Looper , it works nice.
i need the Looper because at a point i want to invoke some methods inside which initiate a Handler
thanks in advance
It is because your TimrTask never returns (because of the call to Looper.loop() )
Form The Timertask documentation, emphasis mine (Oracle Documentation, Android's is not that clear) http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html
:
Corresponding to each Timer object is a single background thread that
is used to execute all of the timer's tasks, sequentially. Timer tasks
should complete quickly. If a timer task takes excessive time to
complete, it "hogs" the timer's task execution thread. This can, in
turn, delay the execution of subsequent tasks, which may "bunch up"
and execute in rapid succession when (and if) the offending task
finally completes.
So what happens is that your TimerTask is run in the single thread of your Timer and as it's run method never returns it bloks the thread, which cannot run the new scheduled itereation of your TimerTask anymore.

Increment sleep/wait time until required

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.

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 make service for working by timer?

I have following task: to make service which executes and gets data from Internet every 10 minutes. I try to use combination Service + Timer, but in this case I can't control service (I executes TimerTask with delay in onCreate() method of service, and when I interrupt service TimerTask won't stopped). I need 2 buttons only: "start service" and "stop service". What is the best way in this case? Thank you for helping.
You should use the AlarmManager. See this question Android: How to use AlarmManager for help on that. There is no need to waste a users memory by keeping your service alive doing nothing for 10 minutes. Also, if the phone is asleep, your timer will not run. By using the AlarmManager, the phone will automatically be woken up every 10 minutes and your service can be called to perform its internet download task.
If I understand you well, you want to know how to stop a TimerTask when you interrupt your Service?!
If so, read on, otherwise please explain better.
To stop a TimerTask from executing again (assuming it was scheduled to run repeatedly) you must call the cancel() method. The preferred method is to let the TimerTask itself call the cancel() method after checking some boolean flag which can be set externally.
For example:
class MyTimerTask extends TimerTask() {
private boolean alive = true;
public void run() {
if (alive) {
// do something
} else {
cancel();
}
}
public void stop() {
alive = false;
}
}
Then, it's pretty obvious that when you interrupt your service, you just have to call MyTimerTask.stop().

Categories