CIS 260 The Runnable Interface

As we bask in the glorious afterglow of the last example, we are blissfully unaware of lurking problems which are about to strike. Fortunately, they aren't striking just yet. First, we will examine the problem of wanting to extend a class AND have the class also operate as a Thread. We can't extend two classes. This is where the Runnable interface comes into play. Interfaces provide a sort-of multiple inheritance. While true multiple-inheritance always seems unwieldly, Java's interfaces are relatively straightforward.

This next example demonstrates the same problem we have been dealing with, but this time using a Runnable interface. Look in the ActionListener for btnStart to see how the thread is created and then started. The thread is created with a Thread constructor, passing the object itself as the thread (which is why we need to implement the Runnable interface).

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

public class TThread4 extends JFrame implements Runnable {
   Thread ctr = null;
   JButton btnStart, btnStop;
   JLabel lblNum;
   int count = 0;
   boolean running = false;

   // override run() to implement Runnable
   public void run() {
      while (running && (++count < 100)) {
         lblNum.setText(Integer.toString(count));
         try {
            Thread.sleep(100);
         } catch (InterruptedException e) {
            System.out.println("Application Interrupted");
         }
      }
   }

   public static void main(String[] args) {
      TThread4 app = new TThread4();
      app.addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
      app.init();
      app.pack();
      app.setVisible(true);
   }

   public void init() {
      Container c = this.getContentPane();
      c.setLayout(new GridLayout(3,1));
      lblNum = new JLabel("Running Total");
      btnStart = new JButton("Start");
      btnStop = new JButton("Stop");
      btnStop.setEnabled(false);

      btnStart.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnStart.setEnabled(false);
            btnStop.setEnabled(true);
            running = true;
            ctr = new Thread(TThread4.this);
            ctr.start();
         }
      });

      btnStop.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            running = false;
            btnStart.setEnabled(true);
            btnStop.setEnabled(false);
         }
      });

      c.add(lblNum);
      c.add(btnStart);
      c.add(btnStop);
   }
}

Previous: using threads

Next: shared resource problems I