This week you will NOT need to submit your solutions.

Objectives

  • To understand how threads allow a program to multi-task
  • To use threads for networking to prevent the program from blocking when trying to receive messages

Threads in Java

An example without threads

To see why threads are useful, let us first look at an example that does not use threads:

  • We will simulate a dog-race viewed aerially: two lines that grow randomly across the screen until one reaches the end.

Look at Race1.java program in the threads.dograce package:

  • If you run it you can see, it’s a very crude depiction of a dog-race
  • Each dog sleeps for a random amount of time (Uniformly distributed in [300,600] milliseconds).
  • After waking up, a dog runs for a random distance (Uniformly distributed in [50,100] pixels) and goes to sleep again.

Let us examine the code in more detail:

  • The basic components of the frame are: two buttons and a canvas.
  • Pressing the start button starts the race. (This is done in the method race()).
  • Each Dog instance:
    • Keeps track of its position.
    • Generates the next position and draws the ground covered so far.
  • The simulation keeps track of the “next event” (i.e., which dog wakes up next).
  • In the while-loop of method race(), the method sleep() of Thread is used:
    • sleep() is a static method of Thread.
    • Any code can call sleep().
    • The parameter is the number of milliseconds the current thread is put to sleep.
      sleep() throws an exception and therefore requires a try-catch block.
  • Just because we are calling Thread.sleep() does not mean that we are using threads.
    • This just happens to be the class in which Java has placed the sleep() method.
    • The sleep() method “pauses” the current execution for the specified time.
  • Note something interesting (troubling) about our application: you cannot “quit” until the race is over:
    • Thus, the event-handler for “quit” is not called until the race completes.
    • This is not the kind of behavior one expects of a sophisticated application.

Exercise 1: Race1.java program in the threads.dograce package to:

  • Each dog will run as a separate thread.
  • Each such thread will sleep and move on its own.
  • To create and use a thread, use the following steps:
    • Decide which class is going to run as a thread (or which class has the “main-loop” of the thread).
    • Make that class implement the Runnable interface.
    • To implement this interface, the class has to implement a method called public void run().
    • The run() method will be called when the thread is started.
    • Next, to actually run the thread, pass the selected class to a new instance of Thread and call the start() method of the Thread instance.

The same example with threads

Look at Race2.java program in the threads.dograce package:

  • The class Dog now implements the Runnable interface.
  • The run() method of Dog contains the main loop for a single dog-thread: repeatedly sleep and move until the finish line is crossed.
  • Creating a thread is as simple as passing a Dog instance to the constructor of Thread:
    Thread dThread1 = new Thread (d1);
    
  • To actually start the thread going, one calls the start() method of the thread instance:
    dThread1.start();
    

Note:

  • Now you can “quit” the application during the race.
  • Notice what happens when one dog wins: the other dogs complete the race.

Exercise 2: Race2.java program in the threads.dograce package solve the problem of “losers” continuing the race.

To do that have each thread should read the status of the race via a method call:

public boolean raceFinished (boolean set)
 {
     // If set==true, set the race to be over.  
     // Otherwise, return current status.  
 }

Thus, the same method is called by each dog to either (1) indicate that the race is over; or (2) find out whether the race is over.

Networking Threads


Previous

© 2003, Rahul Simha (revised 2017). Further revised by Tim Wood 2018 and Roxana Leontie 2020.</center>