Before we dive into the details of how to create a multithreaded application, let's spend a few minutes talking about what a thread is and why we need them.
Modern operating systems are able to run more than one process at the same time, even if there is only one CPU present on the computer. This is possible because almost all computer programs have some "dead time" that occurs when they are running. Programs that present a GUI experience this lull whenever they are waiting on the user to press a key or click the mouse. If a program accesses a database, it has to wait on the I/O processor to access the hard drive and copy data into memory before it can proceed, causing a lull.
Whenever a program goes into a lull, the CPU swaps this program out and runs another for a time. This creates a perceived improvement in performance and a real improvement in user satisfaction.
By using that same logic, one process can create several other processes and delegate some of its tasks to the others. This would be a good strategy in some circumstances if process creation were less expensive in CPU cycles. The same effect can be achieved for less expense by creating a kind of junior process called a thread. A thread is a type of subprocess that is managed by the main process, not by the operating system. Threads contain their own copies of local variables, their own program counter, and their own life cycle. They do not have nearly the overhead in creation and destruction that full processes do.
The reasons that we want to run more than one thread in the same program are
Some tasks can't be performed without threads. For example, if you press play to run an animation in a window, you need a stop button to halt it. If the only thread is busy running the animation, there is no thread available to notice that the stop button was pressed.
Some tasks can be done in the background, enabling the user to perform other tasks. In old-fashioned word processors, you couldn't do any work while a document was printing. Modern word processors normally perform this task in the background.
Some tasks are naturally multithreaded. Video with sound requires one thread to play the video and another to play the sound.
Some simulations and game programs attempt to imitate the real world by having a lot of action taking place at the same time. Real-time strategy games such as Microsoft's "Age of Empires" or Blizzard's "WarCraft III" are the most popular games of this genre.
Some tasks can be subdivided and processed in parallel. Selecting all the rows in a database that have the word "Smith" in the last name field is an example of this. If the database has one million rows, four threads could each process a portion of the data and combine the results at the end. This could result in a significant reduction in the amount of wall-clock time needed to complete a query. Figure 18.1 shows this example graphically.
Before you run off and create threads left and right, however, you need to be aware of the downside to using threads. Creating and destroying threads consumes both CPU cycles and a certain amount of memory. If the thread will be used heavily, these costs are small. If it will only be used to process a little information before it is destroyed, these costs will be relatively high. In some cases, such as the GUI button, this cost is not avoidable. In other cases, such as the database query, you would not be wise to create multiple threads if you were only going to process 100 rows.