Today we will study about Creating and Running Threads. This lesson is part of Chapter 8.5.1 of Introduction to Programming Using Java.
Creating and Running Threads
In Java, a thread is represented by an object belonging to the class java. lang.Thread (or to a subclass of this class). The purpose of a Thread object is to execute a single method. The method is executed in its own thread of control, which can run in parallel with other threads.
When the execution of the method is finished, either because the method terminates normally or because of an uncaught exception, the thread stops running. Once this happens, there is no way to restart the thread or to use the same Thread object to start another thread.
There are two ways to program a thread. One is to create a subclass of Thread and to define the method public void run() in the subclass. This run() method defines the task that will be performed by the thread; that is, when the thread is started, it is the run() method that will be executed in the thread. For example, here is a simple, and rather useless, class that defines a thread that does nothing but print a message on standard output:
To use a NamedThread, you must of course create an object belonging to this class. For example,
However, creating the object does not automatically start the thread running. To do that, you must call the start() method in the thread object. For the example, this would be done with the statement
The purpose of the start() method is to create a new thread of control that will execute the Thread object’s run() method. The new thread runs in parallel with the thread in which the start() method was called, along with any other threads that already existed. This means that the code in the run() method will execute at the same time as the statements that follow the call to greetings.start(). Consider this code segment:
After greetings.start() is executed, there are two threads. One of them will print “Thread has been started.” while the other one wants to print “Greetings from thread ’Fred’!”. It is important to note that these messages can be printed in either order. The two threads run simultaneously and will compete for access to standard output, so that they can print their messages. Whichever thread happens to be the first to get access will be the first to print its message.
In a normal, single-threaded program, things happen in a definite, predictable order from beginning to end. In a multi-threaded program, there is a fundamental indeterminancy. You can’t be sure what order things will happen in. This indeterminacy is what makes parallel programming so difficult!
Note that calling greetings.start() is very different from calling greetings.run(). Calling greetings.run() will execute the run() method in the same thread, rather than creating a new thread. This means that all the work of the run() will be done before the computer moves on to the statement that follows the call to greetings.run() in the program. There is no parallelism and no indeterminacy.
I mentioned that there are two ways to program a thread. The first way was to define a subclass of Thread. The second is to define a class that implements the interface java.lang.Runnable. The Runnable interface defines a single method, public void run().
An object that implements the Runnable interface can be passed as a parameter to the constructor of an object of type Thread. When that thread’s start method is called, the thread will execute the run() method in the Runnable object. For example, as an alternative to the NamedThread class, we could define the class:
To use this version of the class, we would create a NamedRunnable object and use that object to create an object of type Thread:
Finally, I’ll note that it is sometimes convenient to define a thread using an anonymous inner class (Subsection 5.7.3). For example:
To help you understand how multiple threads are executed in parallel, we consider the sample program ThreadTest1.java. This program creates several threads. Each thread performs exactly the same task.
The task is to count the number of integers less than 1000000 that are prime. (The particular task that is done is not important for our purposes here.) On my computer, this task takes a little more than one second of processing time. The threads that perform this task are defined by the following static nested class:
The main program asks the user how many threads to run, and then creates and starts the specified number of threads:
It would be a good idea for you to compile and run the program or to try the applet version, which can be found in the on-line version of this section.
When I ran the program with one thread, it took 1.18 seconds for my computer to do the computation. When I ran it using six threads, the output was:
The second line was printed immediately after the first. At this point, the main program has ended but the six threads continue to run. After a pause of about seven seconds, all six threads completed at about the same time. The order in which the threads complete is not the same as the order in which they were started, and the order is indeterminate. That is, if the program is run again, the order in which the threads complete will probably be different.
On my computer, six threads take about six times longer than one thread. This is because my computer has only one processor. Six threads, all doing the same task, take six times as much processing as one thread. With only one processor to do the work, the total elapsed time for six threads is about six times longer than the time for one thread.
On a computer with two processors, the computer can work on two tasks at the same time, and six threads might complete in as little as three times the time it takes for one thread. On a computer with six or more processors, six threads might take no more time than a single thread.
Because of overhead and other reasons, the actual speedup will probably be smaller than this analysis indicates, but on a multiprocessor machine, you should see a definite speedup. What happens when you run the program on your own computer? How many processors do you have?
Whenever there are more threads to be run than there are processors to run them, the computer divides its attention among all the runnable threads by switching rapidly from one thread to another. That is, each processor runs one thread for a while then switches to another thread and runs that one for a while, and so on.
Typically, these “context switches” occur about 100 times or more per second. The result is that the computer makes progress on all the tasks, and it looks to the user as if all the tasks are being executed simultaneously. This is why in the sample program, in which each thread has the same amount of work to do, all the threads complete at about the same time: Over any time period longer than a fraction of a second, the computer’s time is divided approximately equally among all the threads.
When you do parallel programming in order to spread the work among several processors, you might want to take into account the number of available processors. You might, for example, want to create one thread for each processor. In Java, you can find out the number of processors by calling the function
which returns an int giving the number of processors that are available to the Java Virtual
Machine. In some cases, this might be less than the actual number of processors in the computer.
Source:
- Chapter 8.5.1 – Creating and Running Threads | Introduction to Programming Using Java
SEE MORE:
- Chapter 8.5.3 – Mutual Exclusion with synchronized | Introduction to Programming Using Java
- Chapter 8.5.5 Volatile Variables | Introduction to Programming Using Java
- Quiz on Chapter 8 | Introduction to Programming Using Java
- Chapter 9.1 Recursion | Introduction to Programming Using Java
- Chapter 9.1.2 Towers of Hanoi | Introduc’tion to Programming Using Java
- Chapter 9.3.1 Stacks | Introduction to Program’ming Using Java
- Chapter 9.4.1 Tree Traversal | Introduction to Program,ming Using Java
- Chapter 10.1.1 Generic Programming in Smalltalk | Introduc’tion to Program ming Using Java
- Chapter 12 Advanced GUI Programming | Images and Resources | Introduction to Program ming Using Java
1 thought on “Creating and Running Threads in Java”