Multiple Background Threads in Android

One of the main things that came out of my Android tinkering today was knowledge of multi-threading. The threading technique used in GenomeSearch had ‘multiple’ threads as well (2), but the implementation was a bit lacking. Without going into too much detail, GenomeSearch has one (main) thread which manages the User Interface, and one background thread that blocks on network I/O. Unfortuantely, the implementation is such that if we had ever needed a third thread, we wouldn’t have been able to add it.

So, with a little help from this conversation on Android Beginners, I wrote up a little snippet to test running multiple background threads in addition to the main UI thread. You can find the code behind the cut (note that you will need to set up all of the other project files for this to work (layout, manifest, etc).

package edwardslab.example;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

//By Josh Hoffman
//for Dr. Rob Edwards' Bioinformatics Lab
//Reference material: http://www.mail-archive.com/android-beginners@googlegroups.com/msg05904.html

public class ThreadedDownloadPOC extends Activity {
//We define our threads as member fields
Thread mBackground1;
Thread mBackground2;
//Define value holder member fields to communicate between the background threads and UI
//(This may be a bit of a hack, but most reference material I've found shows it this way,
//If Google intends anything smarter, the community doesn't understand it!)
String mResHolder1 = "0";
String mResHolder2 = "1";

// Create a new handler object that will handle the messages
// sent to the UI activity from the background thread.

// These handlers set the mResult text fields to the mResultHolder fields' values.
// They are called when the threads conclude their work, via the sendMessage command.
Handler handler1 = new Handler()
{
@Override public void handleMessage(Message msg)
{
TextView mResult1 = (TextView)findViewById(R.id.TextView01);
mResult1.setText(mResHolder1);
mBackground1.stop();
}
};

Handler handler2 = new Handler()
{
@Override public void handleMessage(Message msg)
{
TextView mResult2 = (TextView)findViewById(R.id.TextView02);
mResult2.setText(mResHolder2);
mBackground2.stop();
}
};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//Define our buttons so that we can implement onClick listeners.
final Button button1 = (Button)findViewById(R.id.Button01);
final Button button2 = (Button)findViewById(R.id.Button02);

//Define our threads and what they will do.
mBackground1 = new Thread(new Runnable()
{
// Setup the run() method that is called when the background thread
// is started.
public void run()
{
// Do you background thread process here...
// In my case, strMsgRcvd is a String where I store
// the message received via my socket.

int sum = 0;
for(int i=0; i<1000000; i++){
sum+=i;
}
mResHolder1="" + sum;
// Get a message object to be sent to our handler.
Message myMsg = handler1.obtainMessage();

// Set the data into our handler message.
myMsg.obj = "sum is: ";

// Send the handler message to the UI thread.
handler1.sendMessage(myMsg);

}
});

mBackground2 = new Thread(new Runnable()
{
// Setup the run() method that is called when the background thread
// is started.
public void run()
{
// Do you background thread process here...
// In my case, strMsgRcvd is a String where I store
// the message received via my socket.


int count = 1;
for(int i=0; i<10000000; i++){
count=i;
}
mResHolder2= "" + count;
// Get a message object to be sent to our handler.
Message myMsg = handler2.obtainMessage();

// Set the data into our handler message.
myMsg.obj = "count is: ";

// Send the handler message to the UI thread.
handler2.sendMessage(myMsg);

}
});

/*
* Set up listeners to launch our threads on key press.
* NOTE: pressing either of these a second time crashes the program.
* I'm not sure why it is happening, but since this is only a Proof-of-concept project,
* I'm not going to worry about fixing that aspect. If somebody figures it out, let me know!
*/
button1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
mBackground1.start();
}
});

button2.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
mBackground2.start();
}
});
}
}