Passing Objects Between Threads Introduction All threaded applications need to share data in some form or another. Sometimes multiple threads share a single data repository on an equal footing; other times, the data sharing can be thought of as a Producer/Consumer process. That is, one thread supplies data that another thread processes; the data is not kept around. When this kind of structure is coded casually, it tends to be done in a way that is subject to subtle bugs. Generally, programmers just create a member variable that is used to contain the object; the producer stuffs the object into the variable, and the consumer takes it out and does something with it: public class Tricky { // ... private Object thingy; // running in one thread private void producer() { // ... if (condition) { thingy = someObject; } } // running in another thread private void consumer() { // ... if (thingy != null) { // do stuff with object // in 'thingy' thingy = null; } } } There are a few ways this can fail. The consumer code must contain code to set 'thingy' to 'null', and this might be forgotten. The producer might at some point decide to send another object, and change the value of 'thingy' while the consumer is using it. Also, if the producer wants to pass more than one object to the consumer, then you have to have multiple member variables, and synchronization is necessary to guarantee that the objects are "sent" as a group -- otherwise, if the timing is wrong, the consumer will get some of the objects but not all. Finally, the "passing" of the object or objects is not explicit; unless the code is well-commented, a reader will not readily understand that the member variable is being used as a temporary location for passing; someone updating the code might try to use that variable freely, assuming that it always has some valid value, or even worse, might try to stuff an object in there that isn't appropriate or which breaks the original producer/consumer structure. A Cleaner Way This article suggests a simple class which can help formalize this producer/consumer structure. The idea is to provide a simple way for a thread to send an object to another thread. Here is the basic structure; the methods' arguments have been left out, and will be detailed below: public class OP { // Object-Passer static public synchronized void send(); static public synchronized Object rcv(); } public class Producer { public void method() { OP.send( object ); } } public class Consumer { public void method() { Object object = OP.rcv(); } } Below will be presented two ways of defining the sending of an object: by thread, and by string. Keying on Threads In this form, an object is sent to a particular thread . That is, the producer thread must know exactly what thread should receive the object. Only that thread can receive the object. This simplifies things for the consumer, because the consumer doesn't have to declare what it is; the OP code can tell what thread the consumer is running in, and return the appropriate object to it. public class OP_Thread { static private Hashtable objects = new Hashtable(); // ... static public synchronized void send( Thread thread, Object object ) { objects.put( thread, object ); } static public synchronized Object rcv() { return objects.get( Thread.currentThread() ); } } public class Producer { private Thread theConsumer; public void method() { // ... OP_Thread.send( theConsumer, someObject ); } } public class Consumer { public void method() { // ... Object object = OP_Thread.rcv(); } } Keying on Strings In this variation, the producer must provide a string that serves as a kind of tag for the object. When a consumer asks for an object sent with a particular tag, the OP code returns that object to the consumer. This means that the producer doesn't have to know precisely what thread the object is being sent to; rather, the object's tag suggests a purpose or role for the object, and any thread that wants to grab the object can do so. This can be useful in a situation where multiple producers and/or consumers are working together on similar tasks; any appropriate consumer thread can pick up an object, as needed. public class OP_String { static private Hashtable objects = new Hashtable(); // ... static public synchronized void send( String string, Object object ) { objects.put( string, object ); } static public synchronized Object rcv( String string ) { return objects.get( string ); } } Example: Video Game A video game is a good, simply example of a program that has two distinct threads (or thread groups). For a simple, 80's-style arcade game, a good design is to have a thread that handles the input events, and another thread running in the background that updates the screen. The event thread will run every time the user provides an input event, while the background thread will run at regular intervals to give the impression of smooth motion -- say, ten times per second. In the example below, the event thread will notify the background thread every time the player has hit a "fire" button. It sends an object under the name "shotfired"; the object itself is of class Shot, and represents information about the shot that was fired. Each time through it's infinite loop, the background thread has to check to see if has received any "shotfired" messages, and, if it has, take the necessary steps to update internal tables and add a visual representation of the new shot to the image on the screen. In this kind of situation, what is more commonly done is to spread the logic of adding a new shot between the event code and the background loop. While this can be made to work, it's confusing, and often results in duplication of code as the program gets more complete. With this structure, the event code does nothing except translate a physical user event (a key press, for example) into a logical game event ("shotfired"). The programmer can freely choose the right part of the code to contain the logic of dealing with the new shot. Futhermore, if some other part of the code has decided that, for example, the game is over, then it can simply ignore the "shotfired" message. This is superior to what you often find, which is that the programmer has sprinkled conditionals of the form if (notdone) { // ... } in many (but possibly not all) of the necessary places around the code. In short, decoupling is the idea here. The two threads have very different responsibilities in dealing with this particular event, and by separating them in this way, each thread can do what it does best. Of course, using an OP object is certainly not the only way to do this, but it is what OP's are for. public class Game { public void [some event handler] { // ... OP_String.put( "shotfired", shot ); } public void run() { while (true) { // ... Shot shot = OP_String.get( "shotfired" ); if (shot!=null) { //... } } } } Improvements In the examples above, it is only possible for there to be a single object waiting in a particular slot. This was done for clarity of exposition; in a real application, it may well make sense to allow a number of objects to be queued up at a time. This can easily be implemented by storing the objects inside a Vector which is then stored inside the 'objects' hashtable, instead of storing the object itself directly into the hastable. Also, in the examples shown, when a consumer requests an object and there isn't one waiting, 'null' is returned. This is fine for some applications, but in other ones, it might make sense to have the call to rcv() block until an object arrives. It would also make sense to provide both of these options -- a rcv() and rcvBlocking() method can coexist in the same implementation of an OP class. Finally, you'll notice that I have made the OP classes entirely static. Some people might object to this; after all, you might want to have multiple repositories, each for a different purpose. This would help to avoid conflicts in which two different sections of the code accidentally use the same tag for different purposes, which might happen if two different people write the two different sections of code. The advantage of using an all-static class is that there isn't any need to pass OP objects around explicitly. The size and complexity of the code should determine whether or not the OP technique should be done statically or not.