Threads

In a Java program, each of the simultaneous tasks the computer handles is called a thread, and the overall process is called multithreading. Threading is useful in animation and many other programs. Threads are a way to organize a program so that it does more than one thing at a time. Each task that must occur simultaneously is placed in its own thread, and this often is accomplished by implementing each task as a separate class. Threads are represented by the THRead class and the Runnable interface, which are both part of the java.lang package of classes. Because they belong to this package, you don't have to use an import statement to make them available in your programs. One of the simplest uses of the THRead class is to slow down how fast a program does something.

Slowing Down a Program

The THRead class has a sleep() method that can be called in any program that should stop running for a short period of time. You will often see this technique used in a program that features animation because it prevents images from being displayed faster than the Java interpreter can handle them. To use the sleep() method, call Thread.sleep() with the number of milliseconds to pause, as in the following statement:

Thread.sleep(5000);


The preceding example will cause the Java interpreter to pause for five seconds before doing anything else. If for some reason the interpreter can't pause that long, an InterruptedException will be thrown by the sleep() method. For this reason, you must deal with this exception in some manner when using the sleep() method. One way to do this is to place the Thread.sleep() statement inside a TRy-catch block:

try {
 Thread.sleep(5000);
} catch (InterruptedException e) {
 // wake up early
}


When you want a Java program to handle more than one thing at a time, you must organize the program into threads. Your program can have as many threads as needed, and they can all run simultaneously without affecting each other.

Creating a Thread

A Java class that can be run as a thread is often referred to as a threaded class. Although threads can be used to pause a program's execution for a few seconds, they are often used to the opposite reason: to speed up a program. If you put time-consuming tasks in their own threads, the rest of the program runs more quickly. This often is used to prevent a task from slowing down the responsiveness of a program's graphical user interface. For example, if you have written a Swing app that loads stock market price data from disk and compiles statistics, the most time-consuming task is to load the data from disk. If threads are not used in the app, the program's interface may respond sluggishly as the data is being loaded. This can be extremely frustrating to a user, especially if the person has decided to close the app and return to more pressing matters, like a game of FreeCell. There are two ways to place a task in its own thread:

  • Put the task in a class that implements the Runnable interface.
  • Put the task in a class that is a subclass of Thread.

To support the Runnable interface, the implements keyword is used when the class is created, as in this example:

public class LoadStocks implements Runnable {
 // body of the class
}


When a class implements an interface, it indicates that the class supports some kind of additional behavior in addition to its own methods. Classes that implement the Runnable interface must include the run() method, which has the following structure:

public void run() {
 // body of the method
}


The run() method should take care of the task that the thread was created to accomplish. In the stock-analysis example, the run() method could contain statements to load data from disk and compile statistics based on that data. When a threaded app is run, the statements in its run() method are not executed automatically. Threads can be started and stopped in Java, and a thread won't begin running until you do two things:

  • Create an object of the threaded class by calling the Thread constructor.
  • Start the thread by calling its start() method.

The THRead constructor takes a single argument—the object that contains the thread's run() method. Often, you will use the this keyword as the argument, which indicates that the current class includes the run() method. Listing 19.1 contains a Java app that displays a sequence of prime numbers in a text area.

Listing 19.1. The Full Text of FindPrimes.java
 1: import java.awt.*;
 2: import javax.swing.*;
 3: import java.awt.event.*;
 4:
 5: class FindPrimes extends JFrame implements Runnable, ActionListener {
 6: Thread go;
 7: JLabel howManyLabel = new JLabel("Quantity: ");
 8: JTextField howMany = new JTextField("400", 10);
 9: JButton display = new JButton("Display primes");
10: JTextArea primes = new JTextArea(8, 40);
11:
12: FindPrimes() {
13: super("Find Prime Numbers");
14: setSize(400, 300);
15: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
16: BorderLayout bord = new BorderLayout();
17: setLayout(bord);
18: display.addActionListener(this);
19:
20: JPanel topPanel = new JPanel();
21: topPanel.add(howManyLabel);
22: topPanel.add(howMany);
23: topPanel.add(display);
24: add(topPanel, BorderLayout.NORTH);
25:
26: primes.setLineWrap(true);
27: JScrollPane textPane = new JScrollPane(primes);
28: add(textPane, BorderLayout.CENTER);
29:
30: setVisible(true);
31: }
32:
33: public void actionPerformed(ActionEvent evt) {
34: display.setEnabled(false);
35: if (go == null) {
36: go = new Thread(this);
37: go.start();
38: }
39: }
40:
41: public void run() {
42: int quantity = Integer.parseInt(howMany.getText());
43: int numPrimes = 0;
44: // candidate: the number that might be prime
45: int candidate = 2;
46: primes.append("First " + quantity + " primes:");
47: while (numPrimes < quantity) {
48: if (isPrime(candidate)) {
49: primes.append(candidate + " ");
50: numPrimes++;
51: }
52: candidate++;
53: }
54: }
55:
56: public static boolean isPrime(int checkNumber) {
57: double root = Math.sqrt(checkNumber);
58: for (int i = 2; i <= root; i++) {
59: if (checkNumber % i == 0) {
60: return false;
61: }
62: }
63: return true;
64: }
65:
66: public static void main(String[] arguments) {
67: FindPrimes fp = new FindPrimes();
68: }
69: }


The FindPrimes app displays a text field, a Display Primes button, and a text area, as shown in Screenshot.

Screenshot Running the FindPrimes app.

Java ScreenShot


Most of the statements in the app are used to create the graphical user interface or display a sequence of prime numbers. The following statements are used to implement threads in this program:

  • Line 5: The Runnable interface is supported in the FindPrimes class.
  • Line 6: A THRead object is given a name (go), but isn't created yet.
  • Lines 35–38: If the go thread has a value of null, which indicates the thread hasn't been created yet, a new Thread object is created under the name go. The thread is started by calling the thread's start() method, which causes the run() method of the FindPrimes class to be executed.
  • Lines 41–54: The run() method looks for a sequence of prime numbers beginning with 2, displaying each one in the primes text area component by calling its append() method. The number of primes in the sequence is determined by the value in the howMany text field.
      
Comments