I have got the basics of how Timer and TimerTask work in Java. I have a situation where I need to spawn a task that will run periodically at fixed intervals to retrieve some data from database. And it needs to be terminated based on the value of the retrieved data (the data itself is being updated by other processes)
Here is what I came up with so far.
public class MyTimerTask extends TimerTask {
private int count = 0;
#Override
public void run() {
count++;
System.out.println(" Print a line" + new java.util.Date() + count);
}
public int getCount() {
return count;
}
}
And a class with a main method like so. For now I have trivially used a 15 second sleep to control how long the timerTask runs.
public class ClassWithMain {
public static void main(String[] args) {
System.out.println("Main started at " + new java.util.Date());
MyTimerTask timerTask = new MyTimerTask();
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(timerTask, 0, 5*10*100);
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main done"+ new java.util.Date());
}
The MyTimerTask class will become more complex with the database service calls and so on.
What I want to be able to do is, in the main class, interrogate a value returned by timerTask to dictate when to invoke timer.cancel() and terminate the process. Right now if I try to use the count property of MyTimerTask it doesn't work. So when I tried adding these lines in ClassWithMain
if (timerTask.getCount() == 5){
timer.cancel();
}
it didn't stop the process.
So I'd like any direction on how I might be able to accomplish what I'm trying to do.
private volatile int count = 0; It is better to use 'volatile'.
try this in ClassWithMain:
for(;;) {
if (timerTask.getCount() == 5) {
timer.cancel();
break;
} else{
Thread.yield();
}
}
Related
I have a while function. When it is true I want to proceed it only every 1 second. I can't use Thread.sleep(), because I am making Minecraft plugin and it will stop all processes on the server. Is there another way how to do it?
Thanks for your reply.
What you are looking for is the Bukkit Scheduler. It is integrated into the default plugin API and can be used to solve your task as following:
int taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
#Override
public void run() {
// do stuff
}
}, delay, repeat);
Set the delay to 0 and the repeat to 20 (20 Ticks are 1 second).
Stop it by using:
Bukkit.getScheduler().cancelTask(taskID);
you can create a java.util.TimerTask
which can schedule your task after a specified time delay .
more details here : https://www.geeksforgeeks.org/java-util-timertask-class-java/
If you use Thread.sleep() in the main Thread you will block the main thread and for avoid this you need to create a separate thread pass to then the values you will need for process whatever you want in your thread, some snippet code for clarification:
public static boolean ENABLE_THREAD = true;
public static void main(String args[]){
InnerThread minecraftThread = (new ThreadStack()).new InnerThread();
minecraftThread.run();
}
public class InnerThread implements Runnable{
#Override
public void run() {
int counter=0;
while(ENABLE_THREAD){
try {
//YOUR CODE
System.out.println(counter);
Thread.sleep(1000);
counter++;
if(counter>10){
ENABLE_THREAD = false;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You can use System.currentTimeMillis():
public static void main(String[] args) {
//The while(true) is to keep the next while loop running, otherwise, in
//this example, the condition System.currentTimeMillis()-past>=1000
//won't be true
//It can be changed according to the needs
long past = System.currentTimeMillis();
while(true)
while(System.currentTimeMillis()-past>=1000)
{
/*
*DO what you need to do
*/
past = System.currentTimeMillis();
}
}
This is the simplest solution I can think of. Please check if it works for you.
long start = new Date().getTime();
while(new Date().getTime() - start < 1000L)
{
//Do Something every 1sec
//you need to update the start value everytime
start = new Date().getTime();
}
I need a loop with delay (like a timer) but have problems with the end of it, this is my code:
while(true) {
if (someValue == 10) {
break;
}
//Wait two seconds. <-----
}
System.out.println("While Ended.");
This works fine, but need to be repeated every 2 seconds. I tried with Timer but the "While Ended." message is shown before of the timer end. How can i solve this problem?
I need that this process not freeze the thread. (like while loop).
Precision is not necessary.
You can put Thread.sleep in a while-loop to sleep for a number of seconds. This solution has problems, e.g. it blocks the thread, breaks on interrupts, etc.
Better is to use a ScheduledThreadPoolExecutor and use the schedule method to schedule the task to run every so many seconds. This is correct but you should have some knowledge of how multithreaded programs work or you'll make mistakes and create subtle bugs.
When you need something like a timer than you could use a timer:
import java.util.Timer;
import java.util.TimerTask;
public class TTimer extends TimerTask {
private static Timer timer;
#Override
public void run() {
System.out.println("timer");
}
public void stop() {
timer.cancel();
timer.purge();
this.cancel();
}
public TTimer( long interval) {
timer = new Timer(true);
timer.scheduleAtFixedRate(this, 0, interval);
}
public static void main(String[] args) {
TTimer t = new TTimer(2000);
while( true ) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
}
}
}
Place your code in the run() method, check your condition (somevalue == 10) and call the stop method to shut the timer down.
I have an event listener which detects when the mouse is being moved in a certain pane of my program. From this, I want to be able to perform some action if the mouse stays idle for too long.
I have looked all over earlier today, to try and find an explanation and example which details how to start, stop/cancel and reset a timer but have been bombarded with different ways to try and do this, which has left me quite confused.
I'm following a timer example from here and implementing for my own situation
When this code below is run, it will output "A" every time the mouse stops. This is incorrect, as if I stop the mouse, move it quickly then stop it again, 2 sets of "A" are produced.
This carries on for however many times the stop is produced.
I believe I am missing a 'reset timer' function that will called when the mouse changes to a moving state.
How can I implement this?/Is that even the problem?
public class SomeClass{
//...some fancy code...
if (! isNowMoving) {
System.out.println("Mouse stopped!");
//Start Timer
new PrintingA(5);
} else if (isNowMoving){
System.out.println("MouseMoving");
//cancel timer & reset ready to start
}
public class PrintingA {
Timer timer;
public PrintingA(int seconds) {
timer = new Timer();
timer.schedule(new PrintingTask(), seconds * 1000);
}
class PrintingTask extends TimerTask{
#Override
public void run() {
System.out.println("A");
timer.cancel();
}
}
}
}
I'm not sure this can be useful for your requirement, Timer is 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. Read java document : java.util.Timer
I perfer to have a thread for IdleMonitor and use Apache Stopwatch to monitor idle time.
import org.apache.commons.lang3.time.StopWatch;
public class IdleMonitor implements Runnable {
StopWatch stopWatch;
private final Object monitorObj = new Object();
private boolean isActive;
private long waitTime = 6000; //in milliseconds, put appropriate time to wait
public IdleMonitor() {
isActive = true;
stopWatch = new StopWatch();
}
public void reset() { // call this during MouseMoving event
synchronized (monitorObj) {
stopWatch.reset();
monitorObj.notify();
}
}
public void finish() { // finish idle mointor operation once your operation ends, this will stop the thread
isActive = false;
reset();
}
public void start() { // start monitoring
Thread t = new Thread(IdleMonitor.this);
t.start();
}
#Override
public void run() {
synchronized (monitorObj) {
stopWatch.start();
while (isActive) {
try {
monitorObj.wait(waitTime);
} catch (InterruptedException ex) {
}
long idleTime = stopWatch.getTime();
System.out.println("Idle time " + idleTime);
// do something if idle time beyond your expected idle time.
// you could set isActive=false; if you want to stop monitoring
}
}
}
}
}
I was looking for a Java timer sample and found the code below at
http://www.javaprogrammingforums.com/java-se-api-tutorials/883-how-use-timer-java.html
But if you run the sample, although it does print Timer stops now... it does not return to the command prompt. This is at least what is happening on my Windows XP machine using cmd.exe.
Why does it not return control to the prompt in this case?
import java.util.Timer;
import java.util.TimerTask;
public class TimerSample {
public static void main(String[] args) {
//1- Taking an instance of Timer class.
Timer timer = new Timer("Printer");
//2- Taking an instance of class contains your repeated method.
MyTask t = new MyTask();
//TimerTask is a class implements Runnable interface so
//You have to override run method with your certain code black
//Second Parameter is the specified the Starting Time for your timer in
//MilliSeconds or Date
//Third Parameter is the specified the Period between consecutive
//calling for the method.
timer.schedule(t, 0, 2000);
}
}
class MyTask extends TimerTask {
//times member represent calling times.
private int times = 0;
public void run() {
times++;
if (times <= 5) {
System.out.println("I'm alive...");
} else {
System.out.println("Timer stops now...");
//Stop Timer.
this.cancel();
}
}
}
It does not return to your command prompt because it is not expected to do so.
Timer creates single non-deamon thread to run all tasks. It does not terminate the thread unless you ask it. When you execture task.cancel() method you just cancel the current task, not the whole timer which is still alive and is ready to do something else.
To terminate timer you should call its stop() method, i.e. timer.stop();
In a real program you would keep a copy of the timer object and when eg program is to be closed down do a timer.cancel().
For this simple example, I added the code below after timer.schedule(t, 0, 2000);
try {
Thread.sleep(20000);
} catch(InterruptedException ex) {
System.out.println("caught " + ex.getMessage());
}
timer.cancel();
}
You need to explicitly terminate the Timer using timer.cancel(), e.g.:
class MyTask extends TimerTask {
private int times = 0;
private Timer timer;
public MyTask(Timer timer) {
this.timer = timer;
}
public void run() {
times++;
if (times <= 5) {
System.out.println("I'm alive...");
} else {
System.out.println("Timer stops now...");
//Stop Timer.
this.cancel();
this.timer.cancel();
}
}
}
I've got a program that controls an electronic component. My problem is the part with the countdown. Practically if I call the class CountDown from the main method, it won't return to the main. The program must be always active and it reads the first value in the main for call and start the countdown.
This is the code:
public class CountDown
{
public static int a;
public static Timer timer;
public CountDown()
{
timer = new Timer();
timer.schedule(new DisplayCountdown(), 0, 1000);
}
class DisplayCountdown extends TimerTask
{
int seconds = 15;
public void run()
{
if (seconds > 0)
{
System.out.println(seconds + " seconds remaining");
if(READING BY ELECTRONIC COMPONENT == 1)
{
seconds=15;
} else {
seconds--;
}
} else {
System.out.println("Countdown finished");
CountDown.a=0;
}
}
}
public static void main(String args[])
{
CountDown.a = 0;
while(true)
{
if(READING ELECTRONIC COMPONENT == 1)
{
if (CountDown.a==0)
{
CountDown.a = 1;
new CountDown();
}
}
}
}
I've checked to make sure my suspicions are correct. It's not that your new Countdown() isn't returning to the main method, it's that it returns immediately. What you want is likely to do some kind of waiting in the while(true) loop and checking whether or not the countdown is completed. Something along the lines of:
CountDown countDown = null;
while(true)
{
if (countDown == null || getReading() == 1)
{
if (CountDown.a == 0)
{
CountDown.a = 1;
countDown = new CountDown();
}
}
while (countDown.isRunning())
{
try
{
Thread.sleep(countDown.getRemainingSeconds() * 1000);
}
catch (InterruptedException ex)
{
// Ignore.
}
}
}
Obviously you'll need to implement the isRunning and getRemainingSeconds methods (you could always sleep for a set amount rather than trying to wait exactly the right amount of time if you want).
I'd also recommend trying to make this class better suited for re-use by avoiding the static variables a and timer (use private variables and setters/initialise them in the constructor instead).