Threads: Inter-Thread Communication
Summary
Multi-threaded software development is a non-trivial exercise. Using Java to implement mutli-threaded applications typicaly requires a clear understanding of the fundamentals and issues arising from the use of threads and also how to use the Java thread API.
This article provides a brief overview of Java threading and presents a basic mailbox framework provides a simple interface allowing messages to be sent safely between objects in different threads of execution. Using this framework creating multi-threaded applications is greatly simplified allowing you to concentrate on developing the application business logic.
The code is available for download.
Threading Basics
Systems that have requirements to provide responsive feedback, or that need processing capability across multiple activities present design issues and constraints that can only be effectively resolved through the use of threads. Single threaded applications cannot provide the level of responsiveness and functionality required.
Threading is necessary in order to allow responsive systems to be developed that are capable of apparently allowing multiple activities to be performed simultaneously. An example of this is reading characters from multiple input streams (e.g. sockets receiving client data) whilst at the same time receiving user keyboard input and updating a user interface with time related information.
Not all system environments provide multi-threading capability and require development of specific components to allow multi-threaded applications to execute. However, Java does provide basic threading capability to application developers through the use of the java.lang.Thread class and java.lang.Runnable interface.
The following shows a simple implementation of a class implementing the java.lang.Runnable interface which is called by a thread object.
public class myClass implements Runnable {
public myClass() {
t = new Thread(this);
t.start();
}
public void run() {
// code to run within thread t
}
}
Threads often require to interact with other threads of execution within the system. However, sharing information between threads is not straightforward and has issues regarding data integrity. Therefore any object data to be shared by more than one thread must provide a mechanism to guarantee only one thread has access rights to the data at anyone time. The Java synchronized keyword allows thread-safe code blocks to be defined within an object.
Thread Locking & Monitors
Object data that needs to be accessed by a thread that is not declared local to the method and is also non-atomic (note: long and double are not accessed atomically) must be synchronised.
The following code fragment for retrieving a data point is an example of a non thread-safe implementation, as a separate thread could update the value of y while another thread is retrieving the Point data. This would result in invalid information being retrieved.
public Point getPoint()
{
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
Correcting this to ensure thread safety requires the accessor and mutator methods to be synchronised as follows;
public synchronized Point getPoint()
{
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
public synchronized void setPoint(Point p)
{
x = p.x;
y = p.y;
}
The synchronisation process obtains the object’s monitor (lock) ensuring that no other thread can obtain access to any synchronised code blocks until the monitor is released (exit scope of synchorisation).
Note: Java monitors are re-entrant, eliminating the possibility of a thread deadlocking itself by trying to obtain an object monitor it already holds.
However locking is only one issue in multi-threading, another key aspect is thread synchronisation - thread communication.
Thread Communication
Java provides a basic set of synchronisation methods within java.lang.Object, allowing threads to wait for notification from other threads. Using the wait() and notify() methods, threads can synchronise with each other. However, in order to use these methods, they must be called within a synchronized code block, otherwise an IllegalMonitorException results.
The thread that requires a synchronisation signal from another thread will call on the wait() method for an object. This will set the thread into a suspended mode until another thread sends a trigger by using the notify() method on the same object.
The following is a simple example of a class containing 2 methods, one which contains a thread blocking on the wait(), and the other method containing the notify() statement that will send a signal to the waiting thread on the same object.
public class Receiver {
private Object data;
public void ready(){
synchronized(this) {
this.wait(); // suspended waiting notification from thread
// pick up data deposited from another thread
}
}
public void send(Object msg) {
synchronized(this) {
data = msg;
this.notify();
}
}
}
One of the most useful types of thread communication construct is the mailbox, where messages may be sent to a waiting object for processing. The calling object is decoupled from the waiting object by operating in a different thread of execution, and will send an synchronous message to the Mailbox.
The Mailbox object will hold onto the message in an internal container object and notify the waiting MailboxListener object that a new message is ready for processing. To develop a Mailbox component requires a clear understanding of threading and the Java Thread API. However, once developed the component is available for reuse in other Java projects.
The following describes the Mailbox implementation available for download at the end of this article.

An implementation of the Mailbox component is available for download.
