I am new to timer's and don't know much about them .My problem is i am creating 2 tables dynamically, and when ever a table is create a timer for 10 mins is assigned to it. I.e. the user has to fill that table in 10 mins else the table will be destroyed. I tried a making a small demo in which i print stuff
The code is :
final Timer mytimers = new Timer();
Timer mytimers1 = new Timer();
mytimers1 = new Timer();
final long delay1 = 5*1000;
// mytimers = new Timer();
mytimers.schedule(new TimerTask() {
Long current1 = System.currentTimeMillis();
long check = current1;
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println(current);
System.out.println("\n");
if((current1 + delay1)<current)
{
System.out.println("mytimmer is about to stop");
mytimers.cancel();
}
}
}, 100, 1000);
mytimers1.schedule(new TimerTask() {
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println("in" + current);
}
}, delay1, 1000);
}
but when i tried implementing this int he final project it does not work as i have to make any variable inside the run a final , thus its value can not to be changed !!!
Please let what should i do !!Thank you
i have to make any variable inside the run a final , thus its value can not to be changed!
Either turn these variables into member variables or encapsulate these values in a proper class, instantiate the class and give a reference to that object to the timer task.
Even though the reference is final, the timer task will still be able to do things such as myTableController.destroyTable().
do it like this :
class YourClass{
Timer mytimers = new Timer();
Timer mytimers1 = new Timer();
long delay1 = 5*1000;
mytimers.schedule(new TimerTask() {
Long current1 = System.currentTimeMillis();
long check = current1;
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println(current);
System.out.println("\n");
if((current1 + delay1)<current) {
System.out.println("mytimmer is about to stop");
mytimers.cancel();
}
}
}, 100, 1000);
mytimers1.schedule(new TimerTask() {
#Override
public void run() {
Long current = System.currentTimeMillis();
System.out.println("in" + current);
}
}, delay1, 1000);
}
in your case you have created anonymous 'concrete' class ie TimerTask, and you are trying to access variables which are not in its scope.
So, if the variables you are trying to access are local(method) variables then they should be declared final or the other way around is to declare those variables as instant(member) variables that what i have done above.
Related
I am trying to get the integer input from a jtextfield and set it as the integer for a timer jlabel when the jbutton is clicked but I keep getting this error inside the MouseEvent method
local variables referenced from an inner class must be final or effectively final
Code:
private void timerStartMouseClicked(java.awt.event.MouseEvent evt) {
int a = Integer.parseInt(timerInput.getText());
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
timeLeft.setText(Integer.toString(a));
--a;
if (a == -1){
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
timer.cancel();
} else if(isRunning){
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
}
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
}
I am still new with Timer Events and Mouse Events, I tried to declare a as a global var which still gives me the same error unless I declare it a value within the method but I need to get the input from the jtextfield.
Not tested, but I think this will work.
private void timerStartMouseClicked(java.awt.event.MouseEvent evt) {
final int a = Integer.parseInt(timerInput.getText());
Timer timer = new Timer();
TimerTask task = new TimerTask() {
int localCount = a;
public void run() {
timeLeft.setText(Integer.toString(localCount));
--localCount;
if (localCount == -1){
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
timer.cancel();
} else if(isRunning){
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
}
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
What's going on is that a is a local variable and is going to vanish into the ether when this method ends, therefore it's not safe to use. If the variable is final then it's safe for Java to copy the value of a into your inner class. However you need to modify a so a constant value won't work.
So we just copy the value into a different variable, one inside the inner class. This makes everything work fine, because now the inner class has its own variable to work with.
I'm working on a program that has a prints time only when a function is called. I'm using timer for the continuous adding of seconds.
Timer gameTimer = new Timer ();
TimerTask time = new TimerTask() {
int sec = 0;
public void run()
{
sec++;
}
};
gameTimer.scheduleAtFixedRate(time, 1000, 1000);
However, I cannot use the variable sec outside the run() so I can print it. I tried to place sec outside TimerTask but of course sec++ would not work. Any help? Thanks!
Since only final variables accessible in anonymous class, but with this below hack you can achieve what you want.
final int [] result = new int[1]; // Create a final array
TimerTask time = new TimerTask() {
int sec = 0;
public void run()
{
sec++;
result[0] = sec;
}
};
// Now Print whenver you want it
System.out.println(result[0]);
This way you are not reassigning the array to a new object just changing the content inside it
Just make your own interface extending the original interface.
https://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html
interface CustomTimerTask extends TimerTask {
public int getTicks();
}
CustomTimerTask time = new CustomTimerTask () {
int sec = 0;
#Override
public void run()
{
sec++;
}
#Override
public synchronized int getTicks() {
return sec;
}
};
System.out.println("The time passed is: " + time.getTicks());
Just make sure you make it synchronized because you're working with two threads now.
I want to change the length of my Countdowntimer when it finishs. So I got a Random Number which changes everytime.
standby_time = 15000
standby_counter = new CountDownTimer(standby_time,1000) {
#Override
public void onTick(long millisUntilFinished) {
++standby_zaehler;
}
#Override
public void onFinish() {
...
standby_zaehler = 0;
rndm_groesse = 60000;
random_zahl = r.nextInt(rndm_groesse);
standby_time = random_zahl;
standby_counter.start();
}
};
Where is my fault ? The time is not changing and takes the first value (15sec)
The countdown timers time isnt ment to be changed. You can recreate the timer to alter the time but because you are looking to start it again inside the onFinish() method it would be wise to use a different implementation better suited for this task. The java.util.Timer class does this well.
private Timer timer = new Timer();
private int standby_zaehler = 0;
private Random r = new Random();
public void scheduleNextTimer() {
// reset our countdown
standby_zaehler = 0;
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// 1 second passed, remove it to the countdown
--standby_zaehler;
// we are finished counting down. get a new max seconds
if(standby_zaehler < 0) {
standby_zaehler = r.nextInt(60);
}
}
}, 1000, 1000);
}
As you can see we dont even need to create a new timer, just reset the number and begin again.
I've created GUI timer, it runs exactly how I wanted it to. I have a stop and pause button, when I stop or pause the timer and restart a new one I get Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled
I'm unsure what I'm suppose to do I've read you cant reuse tasks, but I have no clue to solve this. Can someone PLEASE help me out I'm going crazy over this, I always seem to fix one problem but another one pops up.
Heres part of my code which does the countdown
private TimerTask task = new TimerTask(){
#Override
public void run(){
if (countdown()) {
if(minutes < 9 && seconds < 9)
timerOutput.setText("0"+minutes + ": 0" + seconds);
else if(minutes < 9)
timerOutput.setText("0"+minutes + ":" + seconds);
else if(seconds < 9)
timerOutput.setText(minutes + ": 0" + seconds);
}
else
{
System.out.println("Finish!");
timerOutput.setText("Time is up!");
timer.cancel();
startBut.setEnabled(true);
}
}
};
private boolean countdown(){
seconds --;
if (seconds < 0){
minutes--;
seconds = 59;
if (minutes == -1){
return false;
}
}
return true;
}
Well TimerTasks aren't designed to be reused. The best you can do is create a new TimerTask every time you're going to reschedule it.
Although you can't simply restart a Timer, you could create a Timer wrapper class which would act exactly like a Timer but allow a simple restart method that would instantiate a new Timer in the background. For example;
public class RestartableTimer{
private Timer timer;
private long delay, period;
public RestartableTimer(){
timer = new Timer();
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period){
this.delay = delay;
this.period = period;
timer.scheduleAtFixedRate(task, delay, period);
}
public void restart(TimerTask task){
timer.cancel();
timer = new Timer();
timer.scheduleAtFixedRate(task, delay, period);
}
}
A fair warning, this would not allow for polymorphism. You couldn't for example store a RestartableTimer in a Timer reference. You will also still need to instantiate a new TimerTask when you restart. If you wanted (and you knew you would only be reusing the same TimerTask), you could declare a custom and private embedded class in the above and let the wrapper class handle the creation of the new TimerTask. Alternatively you could have the class methods take a TimerTaskFactory which would implement an Interface which required a method that returned a TimerTask.
Below, an example of using the above class;
public static void main(String[] args) throws InterruptedException{
TimerTask task = new TimerTask(){
#Override
public void run() {
System.out.println("Running");
}};
RestartableTimer rt = new RestartableTimer();
System.out.println("Timer starting with one task");
rt.scheduleAtFixedRate(task, 1000, 1000);
Thread.sleep(5000);
System.out.println("Timer restarting with another task");
rt.restart(new TimerTask(){
int count = 0;
#Override
public void run() {
if(count>4) {
System.out.println("Done");
this.cancel();
} else {
System.out.println("Running 2");
count++;
}
}});
}
At TIME = 0, a user calls a method that sets a flag after 10 seconds. (at TIME = 10)
If the user calls the method again at TIME = 2 the flag should NOT be set at TIME = 10, but instead at TIME = 12:
boolean myFlag; // initializes to false
private Timer timer;
public void setFlag() {
// remove old timer if there was one
if (timer != null) { timer.cancel(); timer = null; }
// set the new timer
timer = new Timer();
TimerTask tt = new TimerTask() {
#Override
public void run() { myFlag = true; }
};
timer.schedule(tt, 10000);
}
Are there any cleaner ways to implement this "updated-schedule-time" model? Examples are appreciated.
I would have simply kept it the same but made little changes.
Declare the variables always as variables should be declared and initialized near they are first used.
public void setFlag() {
Timer timer;
timer = new Timer();
// remove old timer if there was one
if (timer != null) { timer.cancel(); }
// set the new timer
TimerTask tt = new TimerTask() {
#Override
public void run() { setFlag(); }
};
timer.schedule(tt, 10000);
}