The Java Programming Language:
Concurrency: Threads and Multithreading
They used to say about President (of the USA) Gerald Ford that he had difficulty walking and chewing gum at the same time. That was probably a little unfair, since presidents, especially presidents of the USA, tend to be subjected to much unflattering criticism. However, if so, then he had difficulty performing actions in parallel, or concurrently. As humans, we are accustomed to performing such actions all the time: watching TV and snacking; jogging and listening to music on our Walkmans; jumping, dunking a basketball, and doing who knows what with a stray elbow or two; and so on.
When we run a computer program, however (a Java program for example), we are accustomed to having it start at the beginning of the main method for some class, and continue to execute statements one after the other until it is finished. Of course it may "branch off" in various directions, or repeat certain actions, or even react to certain "events" caused by user actions or other external input, but in all cases it is doing one thing at a time, or, in the terminology of the current context, it is performing a single thread of execution.
On the other hand, we are familiar with the fact that our computers often do several things simultaneously, or at least seem to do so. For example, we can be simultaneously downloading a large file from the internet, printing another file on our local printer, and working on a job application letter in a word-processing program. Unless our computer has multiple processors, these activities are not really taking place simultaneously, but by using time slicing our operating system permits multi-processing to take place. That is, each of these processes receives, in turn, a small amount of time to work on whatever it's doing, and then the whole time-allotment scheme is repeated. Thus the "illusion" of simultaneous processing is created. In this case, each process works in isolation in its own "workspace" created for it by the operating system, and each is managed independently by that operating system.
Unlike most programming languages, Java makes concurrency primitives available to the application programmer. This means that a programmer can also create the illusion that his or her program is doing two or more things simulataneously as well. And, if the computer on which it is running actually has multiple processors, the program might really be doing those two or more things simultaneously.
The way a Java programmer does this is to specify that the application is to contain two or more threads of execution (also called threads of control, but usually just called threads, or sometimes lightweight processes). This means, in turn, that each thread is permitted to execute "concurrently" with other threads (i.e., actually concurrently in the mulitprocessor case, but only via time slicing or some other scheme in the uniprocessor case). This ability, called multithreading, is one of the major advantages Java has over C++. That is, in Java multithreading is built into the language. In C++, it must be achieved by platform-dependent libraries, just like a GUI in C++ will generally be dependent upon the platform.
Each thread has a life cycle that it must follow between "birth" and "death":
Whenever you start up a JVM to run one of your programs, some threads are automatically set up to deal with various aspects of your program:
The java.lang.Thread class encapsulates all the information about a single thread running in the JVM. Any thread must have a run() method which contains the code to be executed when the thread runs, and there are essentially two ways to create a thread:
To start a thread, you must call its start() method. Note that you do not call the run() method directly.
Sometimes, at least in simple situations, that may be all you have to do. Each thread will then simply perform its task, under the supervision of the JVM, run to completion, and "die a natural death".