Message Passing Concurrency

Here is some sample code demonstrating how to launch multiple background threads in a determined order with a minimal of confusion. This can be done using a single handler and message passing concurrency. Note that all the calls to Thread.sleep are there to mimic a time intensive task. First declare the necessary imports;

import android.os.Handler;
import android.os.Message;
import android.widget.Toast;


Then in onCreate we will launch the first thread on a button click. This thread completes some work, sends a message with what(0) and then completes some more work. When it exits, it sends a second message with what(1) to signal completion.

        // DISPLAY ON CLICK HANDLER
        threadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                //startActivity(intent);
                Thread thread= new Thread( new Runnable() {
                    public void run() {
                        try {
                        Thread.sleep(1000);
                        }
                        catch(Exception e){   
                        }
                        myHandler.sendEmptyMessage(0);
                        try {
                            Thread.sleep(3000);
                        }
                        catch(Exception e){   
                        }
                        myHandler.sendEmptyMessage(1);
                    }
                });
                thread.setDaemon(true);
                thread.start();
            }
        });

Finally, in the handler we will launch a second thread when the first thread fires off an empty message with a what of 0. When the second thread is done it sends a message with what(2). At this point there are two new threads running simultaneously in a determined manner. We can then trap the successful completion of both threads on what(1) and what(2).


    private Handler myHandler= new Handler(){
        @Override
        public void  handleMessage(Message msg){        
            switch(msg.what){
                case 0:
                    this.removeMessages(0);
                    Toast.makeText(Main.this,"Message0", Toast.LENGTH_SHORT).show();
                    Thread thread= new Thread( new Runnable() {
                        public void run() {
                            try {
                                Thread.sleep(3000);
                            }
                            catch(Exception e){}
                            myHandler.sendEmptyMessage(2);
                        }      
                    });
                    thread.setDaemon(true);
                    thread.start();  
                   
                break;
                case 1:
                                            this.removeMessages(1);
                    Toast.makeText(Main.this,"Message1", Toast.LENGTH_SHORT).show();
                    break;
                case 2:
                                            this.removeMessages(2);
                    Toast.makeText(Main.this,"Message2", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    };

Pretty simple! You can also pass data using messages as in:
                       
Message msg= Message.obtainMessage(0);
Bundle b= new Bundle();
b.putString("stringData",outString);
msg.setData(b);
handler.sendMessage(msg);

You can then retrieve the data in the message what(0) handler as in:

Bundle b= msg.getData();
String data="";
if (b != null){
    data= b.getString("stringData");
}

You can minimize concurrency conflicts by passing immutable objects to and from threads and avoiding the use of shared memory from within the threaded code.

JAL
Comments