In the previous chapters, we examined some of the tools necessary to support the synchronization of data between threads. With these tools, we now are able to have our own threads interoperate with each other, with the system threads, or with the threads started by the standard Java libraries. This is possible because the tools allow for a thread to examine and modify shared data in a safe manner without race conditions. The ability to handle data safely provides us with the ability to exchange data, which, in turn, allows us to accomplish tasks in separate threads safely, which ultimately allows us to accomplish our goal.
In other words, we can now say that threading itself is just an implementation detail of our program. Ideally, true threading should feel like just another object that does something. And while threading itself is a powerful tool, in the end all you want to accomplish is to play the audio clip or read the data socket.
In this chapter, we examine some of the uses of threads. We will show how threads solve certain problems, and discuss the implementation details of these solutions, the threads themselves, and the mechanisms that are used to control and synchronize the threads. We will examine threads from the perspective of solving problems instead of examining features of the threading system.
Interestingly, our first set of examples does not require any threads to be created at ...