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?

Multithreaded Numbers

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.

Annotation 2020-03-24 203640As 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:

Annotation 2020-03-24 203928

Annotation 2020-03-24 204107

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:

Annotation 2020-03-24 204357

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:

Annotation 2020-03-24 204651

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:

Annotation 2020-03-24 204801

Annotation 2020-03-24 205056In 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 program:

  • 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

Annotation 2020-03-24 204907