Countdown thread resume problem

B

bojanraic

I've written a simple app that displays current time and lets the user
input time to start the countdown. It works well, except for one
thing: when 'Stop' button is pressed, it should call the pause()
method, and when 'Start' button is pressed again, it should pick up
upon where it left when paused.
When I press 'Stop', the display of countdown time is indeed paused,
but when 'Start' is pressed once again, the display acts as if the
thread was not paused at all.

I am not sure how to fix this, so if someone could help me, I woul dbe
really grateful.
Here is my code:

CDThread.java - the countdown thread - I'm not sure where to put the
synchronized (this) block... maybe that is the problem. Here's the
code:



import java.awt.*;
import java.util.Date;

public class CDThread extends Thread
{
private Thread cdThread = null;
private Date cntdwnDate;
private String cntdwnString;
private boolean shouldPause;
private int secs, mins, hrs, seconds, minutes, hours;
private long endTime, pausedTime;

public CDThread()
{
super("CountDown");

if (!(TPanel.sec.getText().equals("")&&TPanel.min.getText().equals("")&&TPanel.hour.getText().equals("")))
{
secs = Integer.parseInt(TPanel.sec.getText());
mins = Integer.parseInt(TPanel.min.getText());
hrs = Integer.parseInt(TPanel.hour.getText());
}
else
{
secs = 0;
mins = 0;
hrs = 0;
}


long currentMiliseconds = new Date().getTime();
endTime = currentMiliseconds + secs*1000 + mins*60*1000 +
hrs*60*60*1000;
cntdwnDate = new Date(endTime);
start();

}

public void pause()
{
shouldPause = true;
pausedTime = System.currentTimeMillis();
}

public synchronized void pickUp()
{
shouldPause = false;
endTime = endTime - pausedTime + System.currentTimeMillis();
notifyAll();
}

// run() method
public void run()
{
while(true)
{
try
{
Date currentDate = new Date();
if (cntdwnDate.after(currentDate))
{
long dateDifference = cntdwnDate.getTime() -
currentDate.getTime();

dateDifference = dateDifference/1000;

// Get seconds
int seconds = (int) dateDifference%60;

// Get minutes
dateDifference = dateDifference/60;
int minutes = (int) dateDifference%60;

// Get hours
dateDifference = dateDifference/60;
int hours = (int) dateDifference%24;

// Countdown string
cntdwnString = hours + " hours, " + minutes + " minutes, " +
seconds + " seconds remaining...";

synchronized (this)
{
while (shouldPause)
{
try
{
wait();
}
catch (Exception e) {}
}
}
}
else
cntdwnString = "Done!";

TPanel.cntdwnLabel.setText(cntdwnString);

// Sleep for a second
Thread.sleep(1000);

if (cntdwnString.equals("Done!"))
stop();
}
catch (InterruptedException e)
{
stop();
}
}
}
}


TPanel.java - panel to layout the GUI components

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;

class TPanel extends JPanel implements ActionListener
{
private JButton start, stop, clear;
protected static JLabel timeLabel, cntdwnLabel, minLabel, secLabel,
hourLabel;
protected static CDThread cntdwnThread = null;
private static String cntdwnLabelString, timeString;
private SimpleDateFormat timeFormat;
protected static int hrs, mins, secs;
private JPanel panel1, panel2, panel3;
private javax.swing.Timer t;
private DecimalFormat two;
protected static JTextField sec, min, hour;

public TPanel()
{
/*set up GUI components*/

setLayout(new BorderLayout());

panel1 = new JPanel(new BorderLayout());
panel2 = new JPanel(new FlowLayout());
panel3 = new JPanel(new FlowLayout());

start = new JButton("Start");
stop = new JButton("Stop");
clear = new JButton("Clear");

start.addActionListener(this);
stop.addActionListener(this);
clear.addActionListener(this);

sec = new JTextField(4);
min = new JTextField(4);
hour = new JTextField(4);

timeLabel = new JLabel(timeString);
timeLabel.setHorizontalAlignment(JLabel.CENTER);

cntdwnLabelString = " ";
cntdwnLabel = new JLabel(cntdwnLabelString);
cntdwnLabel.setHorizontalAlignment(JLabel.CENTER);

hourLabel = new JLabel("Hrs ");
secLabel = new JLabel("Secs ");
minLabel = new JLabel("Mins ");

panel3.add(hourLabel);
panel3.add(hour);
panel3.add(minLabel);
panel3.add(min);
panel3.add(secLabel);
panel3.add(sec);

panel2.add(start);
panel2.add(stop);
panel2.add(clear);

panel1.add(timeLabel, BorderLayout.NORTH);
panel1.add(cntdwnLabel, BorderLayout.CENTER);

add(panel3, BorderLayout.NORTH);
add(panel2, BorderLayout.CENTER);
add(panel1, BorderLayout.SOUTH);

/*set up the timer to display current time*/

two = new DecimalFormat("00");

t = new javax.swing.Timer(1000,
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Calendar now = Calendar.getInstance();
int h = now.get(Calendar.HOUR_OF_DAY);
int m = now.get(Calendar.MINUTE);
int s = now.get(Calendar.SECOND);
timeString = "Time: " + two.format(h) + ":" + two.format(m) + ":"
+ two.format(s);
timeLabel.setText(timeString);
}
});
t.start(); // Start the timer
}
public void actionPerformed(ActionEvent ae)
{
Object source = ae.getSource();

if (source == start)
{
if (cntdwnThread == null)// if there is no thread
cntdwnThread = new CDThread();// make a new thread

else // if one is running
cntdwnThread.pickUp(); // call CDThread's pickUp() resume method
}
else if (source == stop)
{
if (cntdwnThread != null)
cntdwnThread.pause();// call CDThread's pause() method
}
else if (source == clear)
{
hrs = 0;
mins = 0;
secs = 0;
if (cntdwnThread != null)
{
cntdwnThread.stop(); //stop the thread
cntdwnThread = null;
}

/*reset the text fields*/
hour.setText("");
min.setText("");
sec.setText("");

cntdwnLabelString = " ";
cntdwnLabel.setText(cntdwnLabelString);
}
}
}


TFrame.java - driver class

import java.awt.*;
import javax.swing.*;

class TFrame extends JFrame
{
private TPanel timerPanel;

public TFrame()// the constructor

{

super( "TimerTest"); // the title of the frame (window)
Toolkit tk = Toolkit.getDefaultToolkit(); // get toolkit to position
the frame
Dimension dim = tk.getScreenSize(); // get screen size
int height = 220;
int width = 260;
setBounds(((dim.width-width)/2), ((dim.height-height)/2), width,
height); // center the frame on the screen

setResizable(false); // do not allow resizing
Container container = getContentPane(); // get container
timerPanel = new TPanel(); // instantiate new object
container.add(timerPanel);
}
public static void main(String args[]) // method main
{
TFrame timer = new TFrame();
timer.show();
timer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} // end main
}

I really apologize for the length of this message, but I really can't
figure this one out. If someone can compile and run the code and tell
me what needs to be fixed, that'd be great.

Thanks in advance!
 
A

Andrew Thompson

When I press 'Stop', the display of countdown time is indeed paused, ...

Not on my box it didn't. Clicking the button had no effect,
the countdown continued on it's merry way.
I really apologize for the length of this message, but I really can't
figure this one out.

This could have been an SSCCE[1] if you had..

1) Ensured all lines were under 72 chars (line wrap breaks code).
2) Put the imports at the top.
3) Made TFrame public and the other classes default
4) Trimmed about 200 lines from it.

Please do so in future.

[1] <http://www.physci.org/codes/sscce.jsp>
 
B

bojanraic

Andrew Thompson said:
When I press 'Stop', the display of countdown time is indeed paused, ...

Not on my box it didn't. Clicking the button had no effect,
the countdown continued on it's merry way.
I really apologize for the length of this message, but I really can't
figure this one out.

This could have been an SSCCE[1] if you had..

1) Ensured all lines were under 72 chars (line wrap breaks code).
2) Put the imports at the top.
3) Made TFrame public and the other classes default
4) Trimmed about 200 lines from it.

Please do so in future.

[1] <http://www.physci.org/codes/sscce.jsp>


I appreciate your comments, I will try to do so in the future.
Can you help me in detecting what needs to be fixed in the code so the
countdown thread would pause and resume properly?

Tahnks once again.
 
A

Andrew Thompson


I appreciate your comments, I will try to do so in the future.

As you have apparently read the document, you will probably
realise that creating an SSCCE alone might solve the problem.
Can you help me in detecting what needs to be fixed in the code so the
countdown thread would pause and resume properly?

Sure. If producing an SSCCE fails to fix the problem your end,
post it and I'll have a look.
 
B

bojanraic

Andrew Thompson said:
As you have apparently read the document, you will probably
realise that creating an SSCCE alone might solve the problem.


Sure. If producing an SSCCE fails to fix the problem your end,
post it and I'll have a look.

Well, I figured it out. I did not synchronize the thread properly...
Anyway, thanks for willingness to help. And I will bookmark the SSCCE
page. :)
Thanks once again!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top