Java TimerTask Strange Behaviour - java

I have a custom Timer Task that executes once after X seconds in a controller... The scenario which I encountered yesterday happens when I schedule my Timer Task and, instantly, I schedule another time and a third time. Every time I schedule, I create a custom object from a class A and assign it to this timer task (so that it does some work in the run method afterwards).
The strange scenario comes when the custom timer task is executed because itÅ› like I have assigned the third object to the three custom timer task object... Instead of retaining each custom timer task object its corresponding instance of A... I will investigate meanwhile the API...
#RequestMapping(value = "execute", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE})
#ResponseBody
public void executeTimerTask(#RequestParam("task") String task) {
new java.util.Timer().schedule(new java.util.TimerTask() {
#Override
public void run() {
System.out.println("task: " + task);
}
}, 10 * 1000);
}
This would be more or less a copy of what I have before creating the custom timer task... If I execute quickly and hit this endpoint three times (before 10 seconds), when the timer task is executed what it's going to be printed is the value from the third endpoint execution. What I want is a way of retaining each value when the task is executed...

Related

Run a task continuously without delay inside a Java TimerTask

How do I run a specific set of instructions inside the TimerTask continuously without delay for a set amount of time ? Below are the codes I am attempting to implement the above.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println("Test started at: " + new Date());
// Do something continuously without delay
System.out.println("Test finished at: " + new Date());
}
}, 0);
The second parameter to the schedule method is the time to begin the timer task (or delay relative to now), not the length of time that the timer will execute for.
It's not completely clear from your question but I'm assuming you want the task to start and stop at particular times (or delays relative to now) in the future. If so, the way I would approach this is to create a Thread that does the task you need. Since a TimerTask is a Runnable that is executed as a Thread once the Timer starts it, you can just use an instance of that TimerTask. Ensure that Runnable contains a settable field like running. In that Thread, run your task in a while loop like this:
public void run() {
while(running) { /* do my task */ }
}
Then, use one Timer to schedule the Runnable to start at the time you need. Use another Timer to set the running parameter of the same Thread to false at the time you want it to stop. The running parameter should be volatile to ensure that changes to it from the second timer Thread are seen by the first timer Thread immediately. So it would look something like this (not tested):
class StoppableTimerTask extends TimerTask {
private volatile boolean running = true;
public void stopRunning() { this.running = false; }
public void run() {
while(running) { /* do my task */ }
}
}
final StoppableTimerTask task = new StoppableTimerTask();
timer.schedule(task, startTime);
timer.schedule(new TimerTask() {
public void run() {
task.stopRunning();
}
}, stopTime);
Depending on what your "something" is, you may also want to look into Thread interrupts. For example, if it is doing blocking IO, your code won't loop and check the running value until the blocking IO completes. Interrupting the thread (may) cause that to happen. See http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupt--. This may or may not work, and it can be tricky to get right, so if you need this Thread to exit as close to the desired time as possible, prefer running blocking I/O and similar operations with smaller timeouts so that the thread can check whether it should continue to run more often.
UPDATE: As per the comment indicating that the task should start right away, it becomes even simpler. The initial task doesn't even need to extend TimerTask -- it can just be a regular Thread that is started immediately. The timer is only needed to stop it at the specified future time.

Call method after X time in java

I am using java 8 and netty(async), i have client server application.I i want call some method after X time for each channel.
I tried java.util.TimerTask, the problem is that the run method wont get any arguments, i want to run the method with argument, how can i run method after X seconds?
I have tried:
import java.util.TimerTask;
public class MyTimer extends TimerTask {
public void run() {
//TODO: read from object
}
}
You just use Timer with schedule with delay
Timer time= new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
//TODO: read from object
}
}, delay);
delay - delay in milliseconds..
Use :-
public void scheduleAtFixedRate(TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals, separated by the specified period.

How can I use time in Java to manipulate code?

I'm trying to test the use of time in Java to manipulate code. So let's say I have a app with an egg. The egg won't hatch until 60 seconds have passed in the application, what method or class would I use to do this?
The Timer class should do what you are after:
A facility for threads to schedule tasks for future execution in a background thread. Tasks
may be scheduled for one-time execution, or for repeated execution at
regular intervals.
You can take a look at a simple example available here.
You can use timer in a way like this
Timer timer = new Timer();
If you want your code to run multiple times:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your logic here
// Your logic will run every 60 second
System.out.println("egg hatched");
}
}, 0, 60000);
If you want it to run only one time
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your logic here
System.out.println("egg hatched");
}
}, 60000);
You can read more about class timer in java here
The easiest old-fashioned single thread approach is
Thread.sleep(60*1000);
System.out.println("egg hatched");
And there is no guaranty that it print exactly after minute
System.currentTimeMillis() returns the current time of the system in milliseconds to your. So you need to create a Thread checking for the current time in a while loop an react to it.
Try run it it a separate scheduled thread;
ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
Runnable hatcher = new Runnable() {
#Override
public void run() {
egg.hatch();
}
};
scheduler.schedule(hatcher, 60, TimeUnit.SECONDS);

Blackberry - Call a method after a specified time

After creating a session, i want to call a method again & again after a specific time - i.e. 5 sec.
But when i call a method it gives me an error. Here is the sample code.
public class RunFunction extends MainScreen{
public RunFunction()
{
//Call Function again and again after 5 sec
setTitle("Timer");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
}
}, 5000);
}
}
I need help related to this. Can you provide any sample code?
From the BlackBerry docs on the Timer class:
A facility for threads to schedule tasks for future execution in a background thread.
So, the first thing to understand is that whatever work you do in the run() method will be run on a background thread. Background threads are not allowed to modify the UI directly. You're probably getting an IllegalStateException by doing that.
Maybe this is just test code, but this code
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
is a little confusing. It creates a BasicEditField, but only uses it to get the String value passed in to it. Just instantiating a field does not add it to a screen. So, you would need to call
add(b);
after this code for the edit field to show. But again, that would be modifying the UI directly. So, in your case, you probably just need to wrap your code with a call to UiApplication#invokeLater():
timer.schedule(new TimerTask() {
public void run() {
// this code executed on background thread -> not UI safe!
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// this code safely executed on UI thread
BasicEditField b = new BasicEditField("Hello", "");
add(b);
String a = b.getText();
Dialog.alert("Value " +a);
}
});
}
}, 5000);
Next, calling Timer#schedule(TimerTask,long) will only schedule your task to run once, after 5000 milliseconds. If you want it to run again and again, use the version of schedule(TimerTask,long,long) that takes three parameters. The last parameter is the amount of time between each call to your timer task's run() method.
This example on Timer and TimerTask java class provides some insights on what you want to do:
http://javaprogramming.language-tutorial.com/2012/02/demonstrate-timer-and-timertask.html

Servlet on startup that triggers an event after regular interval of time using timer class?

I have a servlet that starts on start of tomcat. I need a functionality in that servlet that triggers the event after a regular interval of time i.e 1 hour and
runs in the back ground? Here is my code :-
in main method
MyTask contentTask = new MyTask();
long interval = 60 * 60 * 1000;
Timer timer = new Timer();
timer.schedule(contentTask, new Date(), interval);//line 1
System.out.println("line2");//line2
MyTask
public class MyTask extends TimerTask {
#Override
public void run() {
System.out.println("Inside my task");
}
}
i am expecting as soon control comes to line 2 , run method gets executed and then it keeps on execting the task after ever 60 minutes like background thread does. But
control does not come to run method after line 2. I am not sure what i am missing here and why run method is not getting executed?
Edit:- I think problem is with interval value if i make it one minute i.e 1 * 60 * 1000; contol comes to run method . Looks like even the first time task will be executed after specified time interval i.e 60 minutes but i want to execute the task immediately as soon as it executes the line 1 and then repeat it after 60 minutes How to go for this?
May be you should start as daemon. new Timer(true)
It seems to me that you are looking for a ServletContextListener. You can execute code at the deployment before everything else. In this code you use Executors instead of a "Vanilla" Thread, and schedule it.
#WebListener
public class GlobalContext implements ServletContextListener {
private ServletContext app;
private ScheduledExecutorService scheduler;
//What to do when app is deployed
public void contextInitialized(ServletContextEvent event) {
//Init Context
app = event.getServletContext();
//In my case I store my data in the servlet context with setAttribute("myKey", myObject)
//and retrieve it with getAttribute("myKey") in any Servlet
// Scheduler
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new AutomateRefresh(), 0, 60, TimeUnit.MINUTES);
}
//Do not forget to destroyed your thread when app is destroyed
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdown();
}
//Your function
public class AutomateRefresh implements Runnable {
public void run() {
//Do Something
}
}
}
FYI, Executors is part of Java 5 and further.

Categories