7.2.3 Interaction between Threads

Up to now, we have only considered threads without any interaction. Such threads run asynchronously. There is one way of interaction: a thread can be blocked for some time. For instance, when a thread goes asleep, it blocks itself for a specified amount of time. We discuss various ways that a programmer has to ensure a block on a thread.

Sleeping

The static method Thread.sleep(int ms) makes that the current method is blocked for ms milliseconds.

Priorities

You can specify the priority of a thread with setPriority(). Maximum is 10, minimum is 1, default is 5. Higher priority always goes first, lower priority threads get their turn only when higher priority threads are blocked or dead. Threads of the same priority are treated equally.

In the applet below, you can change the priority on the fly. All balls put themselves to sleep for the same amount of time. But if they awaken, the ball with highest priority gets the first turn. So a slightly higher speed results.

CAVEAT: In current browsers you will encounter both preemptive and non-preemptive scheduling. In preemptive scheduling threads of the same priority will get the same time-slices. Non preemptive scheduling, a second thread will only get its turn when the first thread is explicitly blocked.

Synchronization

Sometimes threads have to be synchronized. For instance, a thread has to wait for data from another one. Synchronization in Java is organized with help of a monitor. As soon as a method of some class is declared synchronized, a monitor is put on each instance of the class. This watchdog will block any other thread that tries to access data that are already accessed by the synchronized method. It is also possible to block/unblock explicitly with the wait/notify method pair of the Object class. We will not go into detail here.

The following two applet are exactly the same, apart from the keyword synchronized. You may notice that the stick is sometimes passed to another ball. It works as follows: if the stick is on top of a ball, it is dragged along. When it is on top of two balls, both balls will try to drag it along. In the first version without synchronization, it might happen that one ball starts displacing the stick when another ball is not ready displacing it. As a result the stick is no longer on top of either ball. In the second version, due to the keyword synchronized in front of the dragging method, there is a monitor on the stick. It prevents that one thread runs the method when another one is not finished with it.


Synchronization is most often used to ensure data integrity. Often a series of operations in a single thread transform correct input to correct output, but the intermediate stages may pass through non-correct forms of the data. So as long as the monitor prevents interference between threads, data integrity is ensured. Note that in the long term, the second applet is somewhat slower, due to the synchronization when two ball overlap. Moreover, in the very long term, the stick in the first applet is dropped at a position where the balls are unable to pick it up.

Suspend and resume

Explicit blocking of a thread can be done by a call to the suspend()-method of the Thread class, the unblocking is done by a call to resume().