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
}
}
}
}
}
Related
I'm coding an assignment and currently everything's working fine. I'm not going to post the whole thing but the essential classes being called and referenced.
Basically, my problem is that I have a GameTimer class to start a Timer in my Game:
public class GameTimer {
GameViewController gvc = GameFrame.gameViewController;
public static boolean isRunning = false;
public int seconds = 0;
public Timer timer = null;
public TimerTask task = null;
public GameTimer () {
timer = new Timer();
}
public void start() {
task = new TimerTask() {
#Override
public void run() {
gvc.updateTime(seconds);
seconds++;
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
System.out.println("Task was started");
isRunning = true;
}
public void stop() {
task.cancel();
timer.cancel();
timer.purge();
isRunning = false;
}
public void restart() {
stop();
start();
}
}
And basically I have different modes that extends a GameModel and references my GameTimer instance in my GameModel class :
public class GameModel {
public GameTimer game_timer = new GameTimer();
//... Rest of instances and classes
}
public class Mode1 extends GameModel {
public Mode1() {
if(!gamer_timer.isRunning)
game_timer.start();
else
game_timer.restart();
}
//.....Rest of methods
}
public class Mode2 extends GameModel {
public Mode2() {
if(!gamer_timer.isRunning)
game_timer.start();
else
game_timer.restart();
}
//.....Rest of methods
}
Basically, my game is a GUI and i have a drop-down box from which I select my modes. My game instantly loads Mode1 when it runs, but when I choose Mode2, it returns a NullPointerException on my
task.cancel();
I've read on some other posts that you have to cancel the TimerTask before the Timer, but whether I put timer cancel before the task cancel
task.cancel
timer.cancel()
it still gives me the same NullPointerException
Here's the error:
Exception in thread "AWT-EventQueue-0" Mode2
java.lang.NullPointerException
at GameTimer.stop(GameTimer.java:32) // task.cancel()
at GameTimer.restart(GameTimer.java:39)
at Mode2.<init>(Mode2.java:15)
Can you help me just figure out why is the task not cancelling.
Why is isRunning static?
Mode1 sets it to true. Mode2 is created and it should read false for isRunning but instead it reads true (class variable = only one used) so instead of calling start( ) it calls restart( ) and gets the NPE because it was never started and so can't be stopped.
I didn't clearly read your explanation line by line but what I can say by seeing your code is that,
Here inside restart() method you are calling stop() first and start() second
public void restart() {
stop();
start();
}
Inside the start() method you are initializing your task object like here
public void start() {
task = new TimerTask()
But as per your code this seems second priority of your code, stop() is called at first, But at that time task was not initialized. I suggest you to rearrange this as per your needs and initialize task anywhere you feel comfortable but be sure you initialized before using.
Thanks for your help. I found the solution. Mode1 is being initialized as I run the game
new Mode1 ();
and the same Mode2. It would initilized when I choose Mode2 in my game. However, because I'm reinitializing the same gameModel over my program, the isRunning would always be false at first because in my GameModel, you see me create a new instance of my GameTimer everytime. So basically, the state of the timer would never be set to true.
I've found the problem to my code but I have figured a solution yet so I will post the solution as soon I am done with it. Thank you for helping
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 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 have a question about the behaviour of Timer class in Java.
This is the code: http://pastebin.com/mqcL9b1n
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.foo();
m = null;
}
public void foo() {
Timer t = new Timer();
t.schedule(new SysPrint(), 200);
}
}
class SysPrint extends TimerTask {
public void run() {
System.out.println("Yes!");
}
}
What happens is that if you run that program, it will print "Yes!" and it's not gonna do anything else (the program doesn't end).
The Java documentation says:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).
As I see this thing, the "last live reference" to the Timer object is gone after the 'foo()' functions ends. And the only task scheduled was the "Yes!" task that was executed, so I guess that after the process printed "Yes!", the Timer object should end and the process should terminate.
What happened here?
Java is not exiting because your thread running the Timer is still kicking around. You have to mark that thread as being a daemon thread before Java will exit. You probably don't have access to the thread itself so unless Timer has a method to mark it so you'll have a hard time doing that. You'll need to manually stop it in a finally clause.
try {
timer = new Timer();
timer.schedule( new SysPrint(), 200 );
} finally {
timer.cancel();
}
I believe the code below should do the trick.
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.foo();
m = null;
}
public void foo() {
Timer t = new Timer();
t.schedule(new SysPrint(), 200);
}
}
class SysPrint extends TimerTask {
SysPrint(Timer timer) {
this.timer = timer;
}
public void run() {
System.out.println("Yes!");
timer.cancel();
}
private Timer timer;
}
When you create a Timer object. A TimerThread is created. And it the internal thread to run your task. You can view the method run() of TimerThread. You can see it has a while loop.
private void mainLoop() {
while (true) {....
The TimerThread not set to a daemon, so the main method execute completely, the jvm not exists.
That why your program is always running and don't stop.
From my readings, it seems that ScheduledExecutorService is the right way to start and stop timers in Java.
I need to port some code that starts and stops a timer. This is not a periodic timer. This code, stops the timer before starting it. So, effectively every start is really a restart(). I am looking for the right way to do this using the ScheduledExecutorService. Here is what I came up with. Looking for comments and insight on things I am missing:
ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> _TimerFuture = null;
private boolean startTimer() {
try {
if (_TimerFuture != null) {
//cancel execution of the future task (TimerPopTask())
//If task is already running, do not interrupt it.
_TimerFuture.cancel(false);
}
_TimerFuture = _Timer.schedule(new TimerPopTask(),
TIMER_IN_SECONDS,
TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
private boolean stopTimer() {
try {
if (_TimerFuture != null) {
//cancel execution of the future task (TimerPopTask())
//If task is already running, interrupt it here.
_TimerFuture.cancel(true);
}
return true;
} catch (Exception e) {
return false;
}
}
private class TimerPopTask implements Runnable {
public void run () {
TimerPopped();
}
}
public void TimerPopped () {
//Do Something
}
tia,
rouble
This looks like a problem:
private boolean startTimer() {
// ......
if (_TimerFuture != null) {
_TimerFuture.cancel(false);
}
_TimerFuture = _Timer.schedule(new TimerPopTask(),
TIMER_IN_SECONDS,
TimeUnit.SECONDS);
// ......
}
Since you're passing a false to cancel, the old _TimerFuture may not get cancelled if the task is already running. A new one gets created anyway (but it won't run concurrently because your ExecutorService has a fixed thread pool size of 1). In any case, that doesn't sound like your desired behavior of restarting a timer when startTimer() is called.
I would rearchitect a bit. I would make the TimerPopTask instance be the thing you "cancel", and I would leave the ScheduledFutures alone once they are created:
private class TimerPopTask implements Runnable {
//volatile for thread-safety
private volatile boolean isActive = true;
public void run () {
if (isActive){
TimerPopped();
}
}
public void deactivate(){
isActive = false;
}
}
then I would retain the instance of TimerPopTask rather than the instance of ScheduledFuture and rearrange startTimer method thusly:
private TimerPopTask timerPopTask;
private boolean startTimer() {
try {
if (timerPopTask != null) {
timerPopTask.deactivate();
}
timerPopTask = new TimerPopTask();
_Timer.schedule(timerPopTask,
TIMER_IN_SECONDS,
TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
(Similar modification to stopTimer() method.)
You may want to crank up the number of threads if you truly anticipate needing to 'restart' the timer before the current timer expires:
private ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(5);
You may want to go with a hybrid approach, keeping references to both the current TimerPopTask as I described and also to the current ScheduledFuture and make the best effort to cancel it and free up the thread if possible, understanding that it's not guaranteed to cancel.
(Note: this all assumes startTimer() and stopTimer() method calls are confined to a single main thread, and only the TimerPopTask instances are shared between threads. Otherwise you'll need additional safeguards.)