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.
The Thread
class has a sleep()
method that you can call in any program that should stop running for a short period of time. You 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 statement causes 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
is thrown by the sleep()
method.
Because this exception might be thrown, you must deal with it 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 all can run simultaneously without affecting each other.
A Java class that can be run as a thread is referred to as a runnable (or
threaded) class. Although you can use threads to pause a program’s execution for a few seconds, programmers often use them for 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 (GUI).
For example, if you have written an application 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 application, the program’s interface might respond sluggishly as the data is being loaded. This can be extremely frustrating to a user.
Two ways to place a task in its own thread include
• Putting the task in a class that implements the Runnable
interface
• Putting 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 contains some extra 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 application is run, the statements in its run()
method are not executed automatically. Threads can be started and stopped in Java, and a thread doesn’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 use the this
keyword as the argument, which indicates the current class includes the run()
method.
Listing 19.1 contains a Java application that displays a sequence of prime numbers in a text area. Create a new empty Java file named PrimeFinder
, enter the text from the listing in the file, and save the file.
1: import java.awt.*;
2: import javax.swing.*;
3: import java.awt.event.*;
4:
5: class PrimeFinder extends JFrame implements Runnable, ActionListener {
6: Thread go;
7: JLabel howManyLabel;
8: JTextField howMany;
9: JButton display;
10: JTextArea primes;
11:
12: PrimeFinder() {
13: super("Find Prime Numbers");
14: setLookAndFeel();
15: setSize(400, 300);
16: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
17: BorderLayout bord = new BorderLayout();
18: setLayout(bord);
19:
20: howManyLabel = new JLabel("Quantity: ");
21: howMany = new JTextField("400", 10);
22: display = new JButton("Display primes");
23: primes = new JTextArea(8, 40);
24:
25: display.addActionListener(this);
26: JPanel topPanel = new JPanel();
27: topPanel.add(howManyLabel);
28: topPanel.add(howMany);
29: topPanel.add(display);
30: add(topPanel, BorderLayout.NORTH);
31:
32: primes.setLineWrap(true);
33: JScrollPane textPane = new JScrollPane(primes);
34: add(textPane, BorderLayout.CENTER);
35:
36: setVisible(true);
37: }
38:
39: public void actionPerformed(ActionEvent event) {
40: display.setEnabled(false);
41: if (go == null) {
42: go = new Thread(this);
43: go.start();
44: }
45: }
46:
47: public void run() {
48: int quantity = Integer.parseInt(howMany.getText());
49: int numPrimes = 0;
50: // candidate: the number that might be prime
51: int candidate = 2;
52: primes.append("First " + quantity + " primes:");
53: while (numPrimes < quantity) {
54: if (isPrime(candidate)) {
55: primes.append(candidate + " ");
56: numPrimes++;
57: }
58: candidate++;
59: }
60: }
61:
62: public static boolean isPrime(int checkNumber) {
63: double root = Math.sqrt(checkNumber);
64: for (int i = 2; i <= root; i++) {
65: if (checkNumber % i == 0) {
66: return false;
67: }
68: }
69: return true;
70: }
71:
72: private void setLookAndFeel() {
73: try {
74: UIManager.setLookAndFeel(
75: "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
76: );
77: } catch (Exception exc) {
78: // ignore error
79: }
80: }
81: public static void main(String[] arguments) {
82: PrimeFinder fp = new PrimeFinder();
83: }
84: }
The PrimeFinder
application displays a text field, a Display Primes button, and a text area, as shown in Figure 19.1.
Most statements in the application are used to create the GUI or display a sequence of prime numbers. The following statements are used to implement threads in this program:
• Line 5: The Runnable
interface is applied to the PrimeFinder
class.
• Line 6: A Thread
object variable is created with the name go
but isn’t assigned a value.
• Lines 41–44: If the go
object variable has a value of null
, which indicates the thread hasn’t been created yet, a new Thread
object is created and stored in the variable. The thread is started by calling the thread’s start()
method, which causes the run()
method of the PrimeFinder
class to be called.
• Lines 47–60: 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.
3.144.114.223