Threads and Concurrent Programming
Threads may be seen as methods that execute at "the same time" as other methods. Normally, we think sequentially when writing a computer program. From this perspective, only one thing executes at a time. However, with today's multi-core processors, it is possible to literally have several things going on at the very same time while sharing the same memory. There are lots of ways that this is done in the real world, and this chapter goes over them in a way that you can apply to your own projects.
14.2 What Is a Thread?
Let’s consider a simple example of a threaded program. Suppose we give every individual thread a unique ID number, and each time it runs, it prints its ID ten times. For example, when the thread with ID 1 runs the output produced would just be a sequence
of ten 1’s: 1111111111.
shown in Figure 14.2, the NumberThread class is defined +NumberThread(in n : int) +run() NumberThread +run() Thread as a subclass of Thread and overrides the run() method. To set the thread’s ID number, the constructor takes a single parameter that
is use to set the thread’s ID number. In the run() method, the thread simply executes a loop that prints its own number ten times:
Figure 14.3: The Numbers object creates several instances of NumberThread and tells each one to start().
Now let’s define another class whose task will be to create many NumberThreads and get them all running at the same time (Fig. 14.3). For each NumberThread, we want to call its constructor and then start() it:
When a thread is started by calling its start() method, it automatically calls its run() method. The output generated by this version of the Numbers application is as follows:
From this output, it appears that the individual threads were run in the order in which they were created. In this case, each thread was able to run to completion before the next thread started running.
What if we increase the number of iterations that each thread performs? Will each thread still run to completion? The following output was generated for 200 iterations per thread:
In this case, only
thread 1 managed to run to completion. Threads 2, 3, 4, and 5 did not. As this example illustrates, the order and timing of a thread’s execution are highly unpredictable. This example also serves to illustrate one way of creating a multithreaded
- Create a subclass of the Thread class.
- Within the subclass, implement a method with the signature void run() that contains the statements to be executed by that thread.
- Create several instances of the subclass and start each thread by invoking the start() method on each