Multithreading and Multiplexing
3.2 Using Threads in Java
3.2.1 Extending the Thread Class
The run method specifi es the actions that a thread is to execute and serves the same purpose for the process running on the thread as method main does for a full application program. Like main , run may not be called directly. The containing program calls the start method (inherited from class Thread ), which then auto- matically calls run .
Class Thread has seven constructors, the two most common of which are:
• Thread()
• Thread(String<name>)
The second of these provides a name for the thread via its argument. If the fi rst is used, the system generates a name of the form Thread-n, where n is an integer starting at zero and increasing in value for further threads. Thus, if three threads are created via the fi rst constructor, they will have names Thread-0 , Thread-1 and Thread-2 respectively. Whichever constructor is used, method getName may be used to retrieve the name.
Example
Thread fi rstThread = new Thread();
Thread secondThread = new Thread("namedThread");
System.out.println(fi rstThread.getName());
System.out.println(secondThread.getName());
The output from the above lines would be:
Thread-0 namedThread
Note that the name of the variable holding the address of a thread is not the same as the name of the thread! More often than not, however, we do not need to know the latter.
Method sleep is used to make a thread pause for a specifi ed number of millisec- onds. For example:
myThread.sleep(1500); //Pause for 1.5 seconds.
This suspends execution of the thread and allows other threads to be executed.
When the sleeping time expires, the sleeping thread returns to a ready state, waiting for the processor.
Method interrupt may be used to interrupt an individual thread. In particular, this method may be used by other threads to ‘awaken’ a sleeping thread before that thread’s sleeping time has expired. Since method sleep will throw a checked excep- tion (an InterruptedException ) if another thread invokes the interrupt method, it must be called from within a try block that catches this exception.
In the next example, static method random from core class Math is used to gener- ate a random sleeping time for each of two threads that simply display their own names ten times. If we were to run the program without using a randomising ele- ment, then it would simply display alternating names, which would be pretty tedious and would give no indication that threads were being used. Method random returns a random decimal value in the range 0–0.999…, which is then multiplied by a scaling factor of 3000 and typecast into an int , producing a fi nal integer value in the range 0–2999. This randomising technique is also used in later thread examples, again in order to avoid producing the same pattern of output from a given program.
Note the use of extends Thread in the opening line of the class. Though this class already implements the Runnable interface (and so has a defi nition of method run ), the default implementation of run does nothing and must be overridden by a defi ni- tion that we supply.
Example
public class ThreadShowName extends Thread {
public static void main (String[] args) {
ThreadShowName thread1, thread2;
thread1 = new ThreadShowName();
thread2 = new ThreadShowName();
thread1.start(); //Will call run . thread2.start(); //Will call run . }
public void run() {
int pause;
for (int i=0; i<10; i++) {
try {
System.out.println(
getName()+" being executed.");
pause = (int)(Math.random()*3000);
sleep(pause); //0-3 seconds.
}
catch (InterruptedException interruptEx) {
System.out.println(interruptEx);
} } } }
Example output from the above program is shown in Fig. 3.1 below.
Fig. 3.1 Example output from the ThreadShowName program
In the above program, each of the two threads was carrying out exactly the same task, which meant that each of them could be created from the same Thread class and make use of exactly the same run method. In practice, of course, different threads will normally carry out different tasks. If we want the threads to carry out actions different from each other’s, then we must create a separate class for each thread (each with its own run method), as shown in the next example.
Example
In this example, we shall again create two threads, but we shall have one thread display the message ‘Hello’ fi ve times and the other thread output integers 1–5. For the fi rst thread, we shall create a class called HelloThread ; for the second, we shall create class CountThread . Note that it is not the main application class ( ThreadHelloCount , here) that extends class Thread this time, but each of the two subordinate classes, HelloThread and CountThread . Each has its own version of the run method.
public class ThreadHelloCount {
public static void main(String[] args) {
HelloThread hello = new HelloThread();
CountThread count = new CountThread();
hello.start();
count.start();
} }
class HelloThread extends Thread {
public void run() {
int pause;
for (int i=0; i<5; i++) {
try {
System.out.println("Hello!");
//Again, introduce an element //of randomness…
pause = (int)(Math.random()*3000);
sleep(pause);
}
catch (InterruptedException interruptEx) {
System.out.println(interruptEx);
} }
} }
class CountThread extends Thread {
int pause;
public void run() {
for (int i=0; i<5; i++) {
try {
System.out.println(i);
pause=(int)(Math.random()*3000);
sleep (pause);
}
catch (InterruptedException interruptEx) {
System.out.println(interruptEx);
} } } }
An example of this program’s output is sho wn below (Fig. 3.2 ).
Fig. 3.2 Example output from the ThreadHelloCount program