JAVAFX, Countdown doesn't work - java

The count down does not work. I'm triggering it through a button.
public void startCountDown() {
timer.schedule(new TimerTask() {
#Override
public void run() {
Platform.runLater(new Runnable() {
public void run() {
countDown--;
countDownText.setText("Time left:" + countDown);
if (countDown < 0)
timer.cancel();
}
});
}
}, 1000); //Every 1 second
}
The countDown variable is set to 60, so the countdown starts at 60
EDIT: The countdown gets stuck at 59 seconds, countDown is an int. No errors. And countDownText is declared as text.
#FXML
private Text countDownText;

There's more than 1 timer class, but I assume you used java.util.Timer
Examining the API shows you used this method:
public void schedule(TimerTask task,
long delay)
Schedules the specified task for execution after the specified delay.
Parameters:
task - task to be scheduled.
delay - delay in milliseconds before task is to be executed.
Throws:
IllegalArgumentException - if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
NullPointerException - if task is null
So your program waits 1 second then executes the run() method, but does not repeat. To make it repeat, you need to use this method:
public void schedule(TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
Parameters:
task - task to be scheduled.
delay - delay in milliseconds before task is to be executed.
period - time in milliseconds between successive task executions.
Throws:
IllegalArgumentException - if delay < 0, or delay + System.currentTimeMillis() < 0, or period <= 0
IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
NullPointerException - if task is null
You can view the complete documentation here: http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html#schedule%28java.util.TimerTask,%20long%29
Here is what I think is correct code:
public void startCountDown() {
timer.schedule(new TimerTask() {
#Override
public void run() {
Platform.runLater(new Runnable() {
public void run() {
countDown--;
countDownText.setText("Time left:" + countDown);
if (countDown < 0)
timer.cancel();
}
});
}
}, 1000, 1000); //Every 1 second
}

Related

How to set the interval in milliseconds so that it will consistently change once every 100ms?

I want to make my millisecond time change every 100ms, but the time I get is inconsistent sometimes the intervals I get are 99, 100 and 101. The interval I want is 100 and consistent.
as below my problem is now the resulting interval will change like number 4 and 5.
19:56:16:096
19:56:16.196
19:56:16.296
19:56:16.397
19:56:16.495
while the result I want is like this below
19:56:16.096
19:56:16.196
19:56:16.296
19:56:16.396
19:56:16.496
here's a screenshot of my App
here's the code I use
public void startTimer(){
carousalTimer = new Timer(); // At this line a new Thread will be created
carousalTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//DO YOUR THINGS
runOnUiThread(new Runnable() {
#Override
public void run() {
long time = System.currentTimeMillis();
SimpleDateFormat sdf3 = new SimpleDateFormat("HH:mm:ss.SSS");
Date date = new Date();
data = sdf3.format(time).toString();
aList.add(data);
get(data);
}
});
}
}, 100, 100); // delay
}
I believe it is part of how Android works. It is a multi-threaded environment where resources are share among multiple processes.
According to the documentation Timer.scheduleAtFixedRate() is the best approach for the following use cases:
In fixed-rate execution, each execution is scheduled relative to the
scheduled execution time of the initial execution. If an execution is
delayed for any reason (such as garbage collection or other background
activity), two or more executions will occur in rapid succession to
"catch up." In the long run, the frequency of execution will be
exactly the reciprocal of the specified period (assuming the system
clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are
sensitive to absolute time, such as ringing a chime every hour on the
hour, or running scheduled maintenance every day at a particular time.
It is also appropriate for recurring activities where the total time
to perform a fixed number of executions is important, such as a
countdown timer that ticks once every second for ten seconds. Finally,
fixed-rate execution is appropriate for scheduling multiple repeating
timer tasks that must remain synchronized with respect to one another.
https://developer.android.com/reference/java/util/Timer#scheduleAtFixedRate
If it is only necessary to be visual perfect, you can set the time relative to the start time. For example by increment an index every 100ms:
final long DELAY = 100; // 100ms delay
AtomicInteger index = AtomicInteger(0);
long startTime = System.currentTimeMillis();
carousalTimer = new Timer(); // At this line a new Thread will be created
carousalTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
long time = startTime + (index.incrementAndGet() * DELAY)
SimpleDateFormat sdf3 = new SimpleDateFormat("HH:mm:ss.SSS");
Date date = new Date();
data = sdf3.format(time).toString();
aList.add(data);
get(data);
}
});
}
}, DELAY, DELAY);

Run method in Timer task is executing two times

I have created a Timer which runs for every 20 seconds. Timer task is taking more than a minute to finish the task. Run method in Timer task is executing two times after 20 seconds before timer task is finished.
class A {
static Timer timer;
TimerTask timertask = new TimerTask({
public void run(){
if(check for some data in the database before inserting )
// Insert records into database
}
}
public test(){
A.timer.scheduleAtFixedRate(imertask,0, 20*1000);
}
}
Two records of the same data are inserted into the database with the time difference of 14 seconds. I am expecting only one record to be in the database Any help on this so much appreciated.
By intent, if the first execution takes more than 20 seconds, the second execution will start immediately after. If the first execution takes more than 40 seconds, the third execution will start immediately after the second execution. And so on until you catch up to having approximately N/20 executions after N seconds.
Documentation link
In fixed-rate execution, each execution is scheduled relative to the
scheduled execution time of the initial execution. If an execution is
delayed for any reason (such as garbage collection or other background
activity), two or more executions will occur in rapid succession to
"catch up." In the long run, the frequency of execution will be
exactly the reciprocal of the specified period (assuming the system
clock underlying Object.wait(long) is accurate).
If you're inserting the same data twice, then it seems that problem would be with however you decide whether you've already inserted that data, rather than with the interval between executions.
If the task runs for about a minute, is that indicative of a bug, or just how long it takes (for example to connect to a remote database)?
This worked fine
class A {
static Timer timer;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("Task is running");
}
};
public void test() {
timer = new Timer();
timer.scheduleAtFixedRate(timerTask, 0, 5 * 1000);
}
public static void main(String[] args) {
A a = new A();
a.test();
}
}
I could not figure why Timer task is running concurrently. I have written same logic and scheduling using Thread and everything is working now.

"runOnUIThread" incrementally running everytime I go back to the activity

I have a timer which runs on the activity's OnCreate method as shown below. When run, the timer increments as it should. Showing:
00:00,
00:01,
00:02,
etc.
final Timer timer = new Timer();
final TimerTask timerTask = new TimerTask(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String timer = sdf.format(new Date(counter * 1000L));
timerText.setText(timer);
counter++;
}
});
}};
timer.schedule(timerTask, 0, 1000);
However, when I revisit the activity, the timer's interval increases. If I revisit it the first time, the interval becomes 2 i.e.
00:00,
00:02,
00:04,
etc.
Revisiting it again makes the interval 3 i.e.
00:00,
00:03,
00:06,
etc.
And the intervals keep incrementing.
I deduced the runOnUIThread method is being run n times, where n is the number of times onCreate has been accessed, but I don't really know what to do about it.
Use the Timer constructor that specifies it to be a daemon new Timer(true) so that if it exits the timer thread exits too.
Also consider cancelling the timer before exiting on onDestroy or onPause for example.

Java: Keep executing if statement

I have an if statement which evaluates the time since the program has begun running and if the time is above a certain threshold, does something. I want this if statement to be checked throughout the whole time the program is running while at the same time have the program continue execution. How would I go about doing this?
Thank you.
The easiest approach would be to use a Timer. With that, you don't need the if logic; you can just use the firstTime argument when scheduling a TimerTask.
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
// do something
}
};
// schedule the task to be run every 100ms (0.1 sec),
// starting after "threshold" milliseconds have past
timer.schedule(task, threshold, 100);
It's not clear from your description if you want to repeatedly "do something" once the time threshold has been exceeded, or if you just want to wait until a certain time has passed and then "do something" once. The above code is for the repeating case. For a one-shot occurrence at some future time, change the last line to:
timer.schedule(task, threshold);
If you're using Swing, you should use a Swing Timer rather than a java.util.Timer. See How to Use Swing Timers for more info.
EDIT: Your comment clarified things a bit. It's fairly easy to do what you described:
Timer timer = new Timer();
TimerTask task = new TimerTask() {
private final long start = System.currentTimeMillis();
#Override
public void run() {
if (System.currentTimeMillis() - start < threshold) {
// do something
} else {
// do something else
}
}
};
// schedule the task to be run every 100ms (0.1 sec), starting immediately
timer.schedule(task, 0, 100);
Note that "do something" and "do something else" can be method calls to an enclosing class.
A cleaner approach might be to define several TimerTasks that are scheduled to execute at different times. The "something else" task that triggers an exception can be scheduled for one-time execution at the threshold time. You can also cancel individual tasks and you can even schedule a task that will cancel another task.

I want to add timer in my applet

I made CountDown.java file and try to add in my Word-trouble.java file (which is main applet) as CountDown ct = new CountDown();
but it is not showing timer in main applet.
Here is coding:
package pack.urdu;
import java.awt.*; //windows toolkit
import java.applet.*; //applet support
public class CountDown extends Applet implements Runnable{
int counter; Thread cd;
public void start() { // create thread
counter = 60; cd = new Thread(this); cd.start();
}
public void stop() { cd = null;}
public void run() { // executed by Thread
while (counter>0 && cd!=null) {
try{Thread.sleep(1000);} catch (InterruptedException e){}
--counter; repaint(); //update screen
}
}
public void paint(Graphics g) {
g.drawString(String.valueOf(counter),25,75);
}
}
You are making a mistake that I see a lot of programmers make: you are mixing up the calculation of elapsed time, with the calculation of the refresh time. If the duration of sleep takes long than a second because of thread contention, your timer will drift.
Instead of tracking a counter that increments every second, just record the start time:
long startTime = System.currentTimeMillis();
Then later, your paint method becomes:
public void paint(Graphics g) {
int elapsedSeconds = (int)(System.currentTimeMillis()-startTime)/1000
g.drawString(String.valueOf(elapsedSeconds),25,75);
}
This method can be called as often, and as many times as you like, and it will always display the correct elapsed seconds. There is no need to increment anything at any specified time.
The only other thing you have to do is to arrange that the screen gets refreshed. (I like to say that you only have to refresh the screen when the user looks at it :-) but since we don't know that we need to refresh more often). The mechanism for this may depend upon the graphic library. One lazy idea is to refresh ten times a second and the screen will be right most of the time.
If you do want to have a thread that sends repaint events, you should have those events sent just at the time that timer clicks over to a new value, and thereby send only one per second. This is done with:
while (stillRunning) {
long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
Thread.sleep(timeTillNextDisplayChange);
repaint();
}
Note that you do not sleep 1000ms! If your system is performing well, this will be very close to 1000ms, but slightly less than that to account for (1) the thread startup delay, possibly caused by thread contention, and (2) the processing time for this loop (which is quite small). In any case, calculating the sleep in this way will prevent timer drift, and assure that your display updates just as the seconds value changes.
See an extended discussion of Common Misunderstandings of Timers on my website.

Categories

Resources