Software Design and Development :: CS 246

06 Teach : Team Activity

Multi-threaded Programs

Objectives

Background

Before continuing, you should have completed this week's preparation assignment.

File, network, and database operations can be very resource expensive, so you should not perform these kinds of operations on a main GUI thread. So, for this assignment, you will use multithreaded programming to be able to run these more complex, time consuming tasks on a background thread, without hanging the GUI.

To minimize the number of variables in this assignment, rather than working with a database or remote server, you will instead simply include a call to Thread.sleep() to simulate the computer spending time working on that task. (In a real project, you wouldn't include sleeping, because it's just wasting time. We are using it for simulation purposes.)

Assignment

For this assignment you will create a new android application that simultaneously counts to 100 by evens and also by odds.

Part I: Starting the background threads

Create a Runnable class containing a run() method that counts to 100 by odd numbers and displays them to standard out (System.out.println()). After displaying each number, include a call to Thread.sleep() to sleep for a quarter of a second (250 milliseconds).

Create a second class that counts 100 by even numbers and displays them. After each one, sleep for 250 milliseconds.

Next, on an empty activity, create two buttons one to start counting by even numbers and one to start counting by odds. In the button event handling method, you should create a new thread and start it running.

Click each button to start the corresponding processes, and watch the console output to ensure that they are both running in the background.

Part II: Updating the UI

Change your code so that when a thread is finished counting, a Toast is displayed to the user letting them know that the counting is complete.

The trick here is that you cannot do things to the UI (i.e. make a toast) on a background thread, it has to be done on the main UI thread. There are various ways to accomplish this, but one approach is that when you create your Runnable object, you can give it a reference to the activity, or a control from that activity. Then, when you are ready you can call a method on the activity, runOnUiThread, that accepts another runnable (or lambda) that will be invoked on the UI thread.

🌟Stretch Challenge🌟

By storing a reference to the activity, or any UI component on the background thread, we have the potential for a memory leak and/or unexpected behavior if that activity is destroyed before the thread finishes (for example, someone accepts a phone call in the middle of the long running process).

To handle this situation, rather than store a reference to the activity, you should store a weak reference to it. This will allow it to be destroyed without your reference keeping it from being garbage collected. This is done by using a WeakReference< T > (where T is the type of class you are holding) for the data type of your member variable. Then, when you want to use the reference, you need to first check that it is not null.

For the stretch challenge, change your code to use weak references to the UI components.

Submission

After completing the activity, compare your answer to the teacher's solution, then complete the accompanying quiz for this assignment on I-Learn.