12 Replies - 304 Views - Last Post: 07 December 2012 - 05:34 AM Rate Topic: -----

#1 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Threading a digital clock

Posted 07 December 2012 - 03:28 AM

Hi there, I have reached the part of my course that covers threading and have run into a brick wall. I understand what threading is, I understand why it is good, what I don't understand is how to write a threaded program. My books give me examples but I just cant seem to relate them to a practical work.

Here is the UI class I have built to house my clock:
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

class DigiClock extends JFrame
{
      //Clock//
   Timer t;
   
      //Buttons//
   JButton startBtn  = new JButton("Start");
   JButton stopBtn   = new JButton("Stop");
   JButton pauseBtn  = new JButton("Pause");
   JButton resumeBtn = new JButton("Resume");
   
      //Labels//
   JLabel clockFace  = new JLabel();
   
      //Docks//
   JPanel buttonDock = new JPanel();
   
      //Handlers//
   ButtonHandler bHandler = new ButtonHandler();

   DigiClock()
   {
      setupGUI();
   }
   
   private void setupGUI()
   {
      Container c = getContentPane();
      c.setLayout(new BorderLayout());
         c.add(BorderLayout.CENTER, clockFace);
         c.add(BorderLayout.SOUTH, buttonDock);
      
      buttonDock.setLayout(new GridLayout(1,4));
         buttonDock.add(startBtn);
            startBtn.addActionListener(bHandler);
         buttonDock.add(stopBtn);
         buttonDock.add(pauseBtn);
         buttonDock.add(resumeBtn);
      
      setTitle("DigiClock v0.1");
      setSize(350,100);
      setVisible(true);
   }

   public class ButtonHandler implements ActionListener
   {
      public void actionPerformed(ActionEvent e)
      {
         if(e.getActionCommand().equals("Start"))
         {
            t.run();
         }
      }
   }
}


And here is my timer, barely modified from the timer I created some weeks ago in another task. This task requires I take this timer and thread it.
public class Timer
{
	int interval;
	Client client;
	
	Timer(Client client, int interval)
	{
		this.client = client;
		this.interval = interval;
	}
	
	public void run()
	{
		while(true)
		{
			for(int i=0; i<interval; i++);
			client.timerFired();
		}
	}
}


public class Client
{
	Client()
	{
		Timer t = new Timer(this, 100000000);
	}
	
	public void timerFired()
	{
		System.out.println("Timer method fired.");
	}
}


There is also a Main.java file that runs a main method that creates one instance of DigiClock and one instance of Client.

Thank you in advance for any help.

Is This A Good Question/Topic? 0
  • +

Replies To: Threading a digital clock

#2 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2774
  • View blog
  • Posts: 11,726
  • Joined: 20-September 08

Re: Threading a digital clock

Posted 07 December 2012 - 03:33 AM

You need to use javax.swing.Timer or you'll have to start writing code that synchronizes with the EventQueue (see EventQueue.invokeLater)
If your course shows code that doesn't use it and doesn't access the gui via the event dispatch thread, then it's wrong i'm afraid.

This post has been edited by g00se: 07 December 2012 - 03:35 AM

Was This Post Helpful? 2
  • +
  • -

#3 Sheph  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 432
  • View blog
  • Posts: 1,020
  • Joined: 12-October 11

Re: Threading a digital clock

Posted 07 December 2012 - 03:41 AM

In order to create a new thread, you have to create a Thread object. You can accomplish this by passing a Runnable (containing the code to run on the thread) to the Thread constructor, or by extending the Thread class and implementing the run() method. Both accomplish the same thing.

Your Timer class has a run() method, which seems to be a perfect candidate to implement Runnable. Then you just do:
new Thread(timerObject).start();

Was This Post Helpful? 1
  • +
  • -

#4 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 03:44 AM

The book doesn't mention swing.Timer, it asks me to use "extends Thread" or "implements Runnable" to create my threaded class. However, every attempt I have made has either come out in error, or left my program in an infinite loop after hitting the start button.. Hence my posting of the virtually unmodified code to ask for advice.
Was This Post Helpful? 0
  • +
  • -

#5 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 04:05 AM

The method I used before was to make Timer an extension of Thread.

From the start button I then invoked the run() method and the result was that the GUI locked up and the DOS ui was displaying the timer ticks as it should. I'm assuming that my program is intended to run the timer thread and the GUI in tandem with each other, though I could be wrong.
Was This Post Helpful? 0
  • +
  • -

#6 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 849
  • Posts: 2,591
  • Joined: 29-July 11

Re: Threading a digital clock

Posted 07 December 2012 - 04:09 AM

Are you required to use separate classes like that? Because if not, one small inner class inside main extend Thread or Runnable could easily update you your clock every second with SwingUtilities or EventQueue.
Was This Post Helpful? 1
  • +
  • -

#7 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 04:32 AM

Here is my next attempt, it will compile, it will run, but it crashes when clicking the start button.

Am I on the right lines or am I completely wrong?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class DigiClock extends JFrame
{
      //Clock//
   Timer t;
   
      //Buttons//
   JButton startBtn  = new JButton("Start");
   JButton stopBtn   = new JButton("Stop");
   JButton pauseBtn  = new JButton("Pause");
   JButton resumeBtn = new JButton("Resume");
   
      //Labels//
   JLabel clockFace  = new JLabel();
   
      //Docks//
   JPanel buttonDock = new JPanel();
   
      //Handlers//
   ButtonHandler bHandler = new ButtonHandler();

   DigiClock()
   {
      setupGUI();
      new Client();
   }
   
   private void setupGUI()
   {
      Container c = getContentPane();
      c.setLayout(new BorderLayout());
         c.add(BorderLayout.CENTER, clockFace);
         c.add(BorderLayout.SOUTH, buttonDock);
      
      buttonDock.setLayout(new GridLayout(1,4));
         buttonDock.add(startBtn);
            startBtn.addActionListener(bHandler);
         buttonDock.add(stopBtn);
         buttonDock.add(pauseBtn);
         buttonDock.add(resumeBtn);
      
      setTitle("DigiClock v0.1");
      setSize(350,100);
      setVisible(true);
   }
   
   public class Timer extends Thread
   {
      int interval;
      Client client;
      
      Timer(Client client, int interval)
      {
         this.client = client;
         this.interval = interval;
      }
      
      public void startTimer()
      {
         Thread tThread = new Thread(this);
         tThread.start();
      }
      
      public void run()
      {
         while(true)
         {
            for(int i=0; i<interval; i++);
            client.timerFired();
         }
      }
   }
   
   public class Client
   {
      Client()
      {
         Timer t = new Timer(this, 100000000);
      }
      
      public void timerFired()
      {
         System.out.println("Timer method fired.");
      }
   }
   
   public class ButtonHandler implements ActionListener
   {
      public void actionPerformed(ActionEvent e)
      {
         if(e.getActionCommand().equals("Start"))
         {
            t.startTimer();
         }
      }
   }
}

Was This Post Helpful? 0
  • +
  • -

#8 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8342
  • View blog
  • Posts: 31,880
  • Joined: 06-March 08

Re: Threading a digital clock

Posted 07 December 2012 - 04:54 AM

What is that supposed to do ?

         while(true)  
         {  
             for(int i=0; i<interval; i++);  
             client.timerFired();  
         }  


Especially the for() loop ?

What is the use of the Client class ?
Was This Post Helpful? 1
  • +
  • -

#9 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 04:57 AM

View Postpbl, on 07 December 2012 - 04:54 AM, said:

What is that supposed to do ?

         while(true)  
         {  
             for(int i=0; i<interval; i++);  
             client.timerFired();  
         }  


Especially the for() loop ?

What is the use of the Client class ?


This part I intend to edit out later to make the clock tick every second. What you see there is actually an exact copy from the example used in the book. I wondered why the for loop was there myself as it has no effect on the outcome of the program, but I thought it would be explained later on (at the time).

Edit: The original code (Timer and Client) comes from a task which taught me about callbacks. I was asked by the book in my threading task to use this code as my base.

This post has been edited by Flukeshot: 07 December 2012 - 04:59 AM

Was This Post Helpful? 0
  • +
  • -

#10 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 05:11 AM

What's strange to me is that when I compile the program with startTimer() having commented out all of it's code.. I get the same error.
C:\Workstation>java Main
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at DigiClock$ButtonHandler.actionPerformed(DigiClock.java:98)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:19
95)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.jav
a:2318)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel
.java:387)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242
)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonL
istener.java:236)
        at java.awt.Component.processMouseEvent(Component.java:6041)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
        at java.awt.Component.processEvent(Component.java:5806)
        at java.awt.Container.processEvent(Container.java:2058)
        at java.awt.Component.dispatchEventImpl(Component.java:4413)
        at java.awt.Container.dispatchEventImpl(Container.java:2116)
        at java.awt.Component.dispatchEvent(Component.java:4243)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322
)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)

        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
        at java.awt.Container.dispatchEventImpl(Container.java:2102)
        at java.awt.window.dispatchEventImpl(window.java:2440)
        at java.awt.Component.dispatchEvent(Component.java:4243)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThre
ad.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.
java:183)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:173)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)

        at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)



But when I bypass the button and just type t.run(); in the client constructor, the timer ticks normally. I feel there is a breakdown in communication between the thread of my timer and the button.

This post has been edited by Flukeshot: 07 December 2012 - 05:14 AM

Was This Post Helpful? 0
  • +
  • -

#11 Sheph  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 432
  • View blog
  • Posts: 1,020
  • Joined: 12-October 11

Re: Threading a digital clock

Posted 07 December 2012 - 05:12 AM

Let me do you a favor: Before you get it to work right, add setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); to your DigiClock constructor, so that when you exit the window, the timer stops eating your CPU. If you don't, you'll have to exit it from your task manager.

Quote

I wondered why the for loop was there myself as it has no effect on the outcome of the program, but I thought it would be explained later on (at the time).

The for loop is simply performing the math of incrementing i Xillion times, which causes your CPU to go through the roof and take a couple extra milliseconds to break out of the loop and call timerFired(). It is supposed to simulate a Timer, but there are already Timer classes for that which don't put that much stress on your processor.
Was This Post Helpful? 0
  • +
  • -

#12 Sheph  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 432
  • View blog
  • Posts: 1,020
  • Joined: 12-October 11

Re: Threading a digital clock

Posted 07 December 2012 - 05:32 AM

... java.lang.NullPointerException
at DigiClock$ButtonHandler.actionPerformed(DigiClock.java:98)

Means go to line 98 of DigiClock.java, and find the object you are calling a method on. In this case, "t" the Timer. NullPointerException means you did not initialize it (at least not anywhere substantial). You initialized A Timer (Not the field in DigiClock) in the constructor of Client, but it immediately goes out of scope.
Was This Post Helpful? 1
  • +
  • -

#13 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Threading a digital clock

Posted 07 December 2012 - 05:34 AM

Okay, it seems like I have accidentally solved my problem thanks to all of your information. I'm going to go play with threads until I understand how and why they work. :)

Solved code: (Got rid of Client entirely and partially rewrote Timer
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

class DigiClock extends JFrame
{
      //Clock//
   Timer t;
   
      //Buttons//
   JButton startBtn  = new JButton("Start");
   JButton stopBtn   = new JButton("Stop");
   JButton pauseBtn  = new JButton("Pause");
   JButton resumeBtn = new JButton("Resume");
   
      //Labels//
   JLabel clockFace  = new JLabel();
   
      //Docks//
   JPanel buttonDock = new JPanel();
   
      //Handlers//
   ButtonHandler bHandler = new ButtonHandler();

   DigiClock()
   {
      setupGUI();
      t = new Timer();
   }
   
   private void setupGUI()
   {
      Container c = getContentPane();
      c.setLayout(new BorderLayout());
         c.add(BorderLayout.CENTER, clockFace);
         c.add(BorderLayout.SOUTH, buttonDock);
      
      buttonDock.setLayout(new GridLayout(1,4));
         buttonDock.add(startBtn);
            startBtn.addActionListener(bHandler);
         buttonDock.add(stopBtn);
         buttonDock.add(pauseBtn);
         buttonDock.add(resumeBtn);
      
      setTitle("DigiClock v0.1");
      setSize(350,100);
      setVisible(true);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
   
   public class Timer extends Thread
   {
      Thread tThread;
      
      Timer()
      {
         tThread = new Thread(this);
      }
      
      public void startTimer()
      {
         tThread.start();
      }
      
      public void run()
      {
         while(true)
         {
            System.out.println("Timer..");
         }
      }
   }
   
   public class ButtonHandler implements ActionListener
   {
      public void actionPerformed(ActionEvent e)
      {
         if(e.getActionCommand().equals("Start"))
         {
            t.startTimer();
         }
      }
   }
}



And thanks Sheph & pbl, I think it was that for loop that was choking the CPU while the rest of my code was fine, making me assume it was an infinite loop.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1