TimerTask not executing? - java

Here is my timer class, This class is designed to constantly update a timer in a view. However, when I run the app the first toast message is displayed to the screen but the second one is never reached (the timerTask's "run" method is never executed). I know that this is probably something simple that I am doing wrong. If anyone could steer me in the right direcion that would be great.
public class MyTimer {
static Timer _timerTask = new Timer();
static int totalSeconds = 1, hour = 0, min = 0, sec = 0;
static String mTimeFormat = "%02d:%02d:%02d";
static String timeTakenString;
public static void start (){
Toast.makeText(GPSMain.context, "Message one", Toast.LENGTH_LONG).show();
TimerTask timer = new TimerTask() {
#Override
public void run() {
Toast.makeText(GPSMain.context, "Message two", Toast.LENGTH_LONG).show();
totalSeconds += 1;
sec += 1;
if(sec >= 60) {
sec = 0;
min += 1;
if (min >= 60) {
min = 0;
hour += 1;
}
}
timeTakenString = String.format(mTimeFormat, hour, min, sec);
postExecute.sendEmptyMessage(0); //update UI
}
private Handler postExecute = new Handler(){
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
GPSMain.timer.setText("Time Taken: "+timeTakenString);
}
};
};
_timerTask.scheduleAtFixedRate(timer,1000,1000);
}
}
code in another file calling this class:
MyTimer myTimer = new MyTimer();
....
myTimer.start();
PROJECT SPEC CHANGED!
My project leader changed the spec of the project so that it no longer needs to update the timer to the UI but rather display it as an end result. Accepting the first answer anyway as it solves the original problem. Will post the new code below.
New code calls:
System.currentTimeMillis();
at the beggining and end of the runcycle, which returns a long. The first value is then subtracted from the second value to calculate the amount of time taken to execute the runcycle. That value is then manipulated and put into a timer format that is displayed at the end as a string.
public static String getTimeTaken(long end, long start){
#SuppressWarnings("unused")
String formattedTime = "", hourHour = "", hourMin = ":", minSec = ":";
long timeTaken = (end-start)/1000, hour = 0, min = 0, sec = 0;
if (timeTaken>9 ){
hourHour = "0";
hourMin = ":0";
if (timeTaken>=60){
if (timeTaken>= 3200){
hour = timeTaken/3200;
timeTaken = timeTaken%3200;
if (hour>9){
hourHour = "";
}
}
min = timeTaken/60;
timeTaken = timeTaken%60;
if (min >9){
hourMin = ":";
}
}
sec = timeTaken;
if(sec%60<10){
minSec = ":0";
}
return formattedTime = (hourHour+hour+hourMin+min+minSec+sec);
}
sec = timeTaken;
minSec = ":0";
hourMin = ":0";
hourHour = "0";
return formattedTime = (hourHour+hour+hourMin+min+minSec+sec);
}

Using thread you cant update your UI for that you have to use runOnUiThread
youractivity.this.runOnUiThread(new Runnable(){public void run(){Toast.makeText(mContext, "Message", Toast.LENGTH_LONG).show();}});

(Very late...just answering in case someone reach this question... scheduling a task doesn't garantee it will run on the proper time... it may take longer, sometimes much longer...)

Related

Why my Java alarm clock code doesn't work properly?

I want the code to trigger the JOptionPane.
Here is the code for the working clock:
new Thread() {
public void run() {
while (true) {
GregorianCalendar cal = new GregorianCalendar();
int hour = cal.get(GregorianCalendar.HOUR);
int min = cal.get(GregorianCalendar.MINUTE);
int sec = cal.get(GregorianCalendar.SECOND);
int AM_PM = cal.get(GregorianCalendar.AM_PM);
String day_night;
if (AM_PM == 1) {
day_night = "PM";
} else {
day_night = "AM";
}
String time = hour + ":" + min + ":" + sec + " " + day_night;
lblClock.setText(time);
}
}
}.start();
Here is code I wrote to trigger alarm, but no 'play sound' is coded yet, because I can't even get the JOptionPane to appear. Why? I want to get the values from spinners, than compare to real time until they meet and than trigger alarm and exit thread. How to fix it?
btnAlarm.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
new Thread() {
public void run() {
txtAlarmSet.setVisible(true);
boolean flag = false;
GregorianCalendar g = new GregorianCalendar();
int hour = Integer.parseInt(spinnerHour.getModel().getValue().toString());
int minute = Integer.parseInt(spinnerMinute.getModel().getValue().toString());
int second = Integer.parseInt(spinnerSecond.getModel().getValue().toString());
int AMorPM;
if (rdbtnAm.isSelected()) {
AMorPM = 0;
} else
AMorPM = 1;
while (flag == false) {
int realHour = g.get(GregorianCalendar.HOUR);
int realMinute = g.get(GregorianCalendar.MINUTE);
int realSecond = g.get(GregorianCalendar.SECOND);
int realAM_PM = g.get(GregorianCalendar.AM_PM);
if (hour == realHour && minute == realMinute && second == realSecond
&& AMorPM == realAM_PM) {
JOptionPane.showMessageDialog(null, "WORKS!"); // <- this doesn't appear!
flag = true;
}
}
txtAlarmSet.setVisible(false);
}
}.start();
}
});
In your checking loop, you need to reacquire the Calendar on every pass, otherwise, you'll just end up re-checking the same time value over and over. Move the line
GregorianCalendar g = new GregorianCalendar();
inside the loop.
Note: This is not a particularly good approach to this problem. What you're doing is called "busy waiting" and it's generally not good for much other than making the CPU get hot. A better approach would be to use an event-driven approach, but that's beyond the scope of this answer.
One major problem I notice is missing } after AMorPM = 1; making it impossible to work for AM.

Time based calculation in Java

I am creating a program that makes a calculation every minute. I don't know exactly how to do this efficiently, but this is some pseudo code I have written so far:
stockCalcTimerH = System.currentTimeMillis() - 1;
stockCalcTimerI = stockCalcTimerH;
stockCalcTimer = System.currentTimeMillis();
if (stockCalcTimerI < stockCalcTimer) {
*do calcuations*
stockCalcTimerI + 60000;
When I print both values out on the screen, it comes out as this:
stockCalcTimerI = 1395951070595
stockCalcTimer = 1395951010596
It only subtracts the number, and doesn't add the 60000 milliseconds...
I'm kind of new to Java, but any feedback helps.
Thanks for reading!!
stockCalcTimerI + 60000;
The new value never gets assigned to a variable.
Change that to:
stockCalcTimerI += 60000;
Which is the same as
stockCalcTimerI = stockCalcTimerI + 60000;
You can use java.util.Timer class to schedule runs.
TimerTask task = new TimerTask() {
#Override public void run() {
// do calculations
}
};
int delay = 0; // no delay, execute immediately
int interval = 60*1000; // every minute
new Timer().scheduleAtFixedRate(task, delay, interval);

How to convert seconds of Timer to hh:mm:ss?

I am truely sorry if asking the same question twice is considered spamming as I already asked about backward timer a hour ago.
But now new problem with it is though I couldn't get anyone's attention to that question again. I have successfully coded the timer thanks to you guys but then I tried to convert seconds tot he hh:mm:ss format but it didn't work. Instead of continuosely going till it is 00:00:00. It just shows the time that I coded it and that's it.
Here's my code.
import java.util.Timer;
import java.util.TimerTask;
public class countdown extends javax.swing.JFrame {
public countdown() {
initComponents();
Timer timer;
timer = new Timer();
timer.schedule(new DisplayCountdown(), 0, 1000);
}
class DisplayCountdown extends TimerTask {
int seconds = 5;
int hr = (int)(seconds/3600);
int rem = (int)(seconds%3600);
int mn = rem/60;
int sec = rem%60;
String hrStr = (hr<10 ? "0" : "")+hr;
String mnStr = (mn<10 ? "0" : "")+mn;
String secStr = (sec<10 ? "0" : "")+sec;
public void run() {
if (seconds > 0) {
lab.setText(hrStr+ " : "+mnStr+ " : "+secStr+"");
seconds--;
} else {
lab.setText("Countdown finished");
System.exit(0);
}
}
}
public static void main(String args[]) {
new countdown().setVisible(true);
}
Move your calculations
int hr = seconds/3600;
int rem = seconds%3600;
int mn = rem/60;
int sec = rem%60;
String hrStr = (hr<10 ? "0" : "")+hr;
String mnStr = (mn<10 ? "0" : "")+mn;
String secStr = (sec<10 ? "0" : "")+sec;
into the run method.
public String getCountDownStringInMinutes(int timeInSeconds)
{
return getTwoDecimalsValue(timeInSeconds/3600) + ":" + getTwoDecimalsValue(timeInSeconds/60) + ":" + getTwoDecimalsValue(timeInSeconds%60);
}
public static String getTwoDecimalsValue(int value)
{
if(value>=0 && value<=9)
{
return "0"+value;
}
else
{
return value+"";
}
}

How to test a timer?

I would like to write a test for a method, that calls observers in a specific intervall, so that they will execute a method. The timer-object runs in its own thread.
Method of timer to be tested
private long waitTime;
public Metronome(int bpm) {
this.bpm = bpm;
this.waitTime = calculateWaitTime();
this.running = false;
}
public void run() {
long startTime = 0, estimatedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();// notify observers here
estimatedTime = System.nanoTime() - startTime;
threadSleepTime = waitTime -estimatedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try {
Thread.sleep(threadSleepTime / 1000000l);
} catch (InterruptedException e) {
// sth went wrong
}
}
}
Snippet from my testclass
private int ticks;
private long startTime;
private long stopTime;
#Test
public void tickTest(){
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = stopTime - startTime;
long lowThreshold = 800000000;
long highThreshold = 900000000;
System.out.println(duration);
assertTrue(lowThreshold < duration);
assertTrue(duration <= highThreshold);
}
#Override
public void update(Observable o, Object arg) {
ticks ++;
if(ticks == 10){
metronome.stop();
stopTime = System.nanoTime();
}
}
Right now, my testclass registers as an observer at the object in question, so that i can count the number of times tick() was executed. The test measures the time before and after the execution, but it feels awkward to me, to test the behaviour this way.
Any suggestions for improving the test?
Sometimes the solution is to use something from a standard library that is sufficiently simple such that it does not need to be tested. I think SchedulerExecuterService will do the trick for replacing the home made Timer being tested here. Note that it is pretty rare to be bit by a bug in library code, but they do exist.
In general though, I think it is okay to create a helper class or use a mocking framework (Mockito) to do something simple like counting "ticks".
P.S. You can replace Thread.sleep(threadSleepTime / 1000000l) with TimeUnit.NANOSECONDS.sleep(threadSleepTime) ... which moves some logic from your code into the standard library.
Based on your comments I changed my code. Instead of implementing the Observer-interface in my testclass, I now created a private class, that implements the interface an registers at my timer.
Thanks for your time and thoughts.
Here is what the code now looks like:
revised testcode
#Test(timeout = 2000)
public void tickTest(){
long lowThreshold = 400000000;
long highThreshold = 600000000;
TickCounter counter = new TickCounter();
metronome.addObserver(counter);
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = System.nanoTime() - startTime;
assertTrue(lowThreshold <= duration);
assertTrue(duration <= highThreshold);
}
private class TickCounter implements Observer{
private int ticks;
public TickCounter(){
ticks = 0;
}
#Override
public void update(Observable o, Object arg) {
ticks++;
if(ticks == 5){
metronome.stop();
}
}
}
snippet from my revised timer
private long expectedTime; // calculated when bpm of timer is set
#Override
public void run() {
long startTime = 0, elapsedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();
elapsedTime = System.nanoTime() - startTime;
threadSleepTime = expectedTime - elapsedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try { TimeUnit.NANOSECONDS.sleep(threadSleepTime); } catch (Exception e) { }
}
}
My biggest issue might have been, that I implemented the observer-interface in my JUnit testcase. So I created a private observer, that specifically counts the number of times, the tick was executed. The counter then stops my timer.
The testmethod measures the timing and asserts, that the needed time is somewhere between my defined limits.
It depends on how accurately you need to measure the time.
If you feel that it's "awkward" is that because you're not sure that the measurement is accurate enough? Do you fear that the OS is getting in the way with overhead?
If so, you may need an external timing board that's synchronized to an accurate source (GPS, atomic standard, etc.) to either test your code, or possibly to provide the trigger for your firing event.
Try this. You also need the time you are expecting. The expected time will be 1000000000/n where n is the number of times your timer needs to tick() per second.
public void run(){
long time = System.nanotime();
long elapsedTime = 0;
// Hope you need to tick 30 times per second
long expectedTime = 1000000000/30;
long waitTime = 0;
while (running){
tick();
elapsedTime = System.nanotime()-time;
waitTime = expectedTime-elapsedTime();
if (waitTime>0){
try { Thread.sleep(waitTime) } catch (Exception e){}
}
time = System.nanotime();
}
}

testing code on time interval

Hi I want to run code over a time period. For example i would like my code to do something like this.
for(every 5 minutes until i say to stop)
automatically read in new value for x
automatically read in new value for y
if (x==y)
//do something
if (x!=y)
//do something else
Timer is what you need.
Naive version. You might consider Timer or the quartz scheduler instead.
while (!done) {
try {
Thread.sleep(5 * 60 * 1000);
x = readX();
y = readY();
if (x == y) {
} else {
}
} catch(InterruptedException ie) {
}
}
System.currentTimeMillis(); Returns you the system time in milliseconds, you can use that.
but first, you need some sort of loop.
This is an alternative to Timer 's
public static final int SECONDS = 1000;
public static final int MINUTES = 60 * SECONDS;
boolean quit = false; //Used to quit when you want to..
long startTime = System.currentTimeMillis();
while (!quit) {
if (System.currentTimeMillis() >= (startTime + (long)5*MINUTES)) {
//automatically read in new value for x
//automatically read in new value for y
if (x==y) {
//do something
} else {
//do something else
}
startTime = System.currentTimeMillis(); //reset the timer for the next 5 minutes
}
}
How about:
Runnable runnable = new Runnable() {
public void run() {
// do your processing here
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 5, TimeUnit.MINUTES);
Call service.shutdown() when you want to stop.

Categories