Concurrent Programming with Java
Lab Manual, Version 1.0, F. Astha Ekadiyanto, 2002.

[Contents] [Next] [Previous]

Lab 4: Introduction to Threads


A Small Jump into Thread

By now your Applet should be able to run in threads. As stated before, we did not actually create a Thread Object. What we did is simply create a Timer Object that handles a background Thread to execute our MobileTask in a timely manner. Thus, we did not defined any Thread related statements directly.

Now we will perform a small jump from our existing codes into defining a Thread.

Modifications in MobileTask Class

Since the TimerTask Class is intended for threadable classes, we will not change a lot from it. The main difference from the previous code is that we now try to handle the periodic repeating task by ourselves rather than using the Timer Class. In order to repeat our run() method periodically, we need to contain the repeated statements in a loop. We will use the while loop for this purpose. The Loop's expression should help us ending the loop process and thus stopping the Thread in an elegant manner.

Change the MobileTask declaration to extend Thread

Now, our MobileTask will not become a TimerTask subClass, but a real Thread instead.

class MobileTask extends Thread
{
	// ... The existing MobileTask statements will still be used
}

Add the loop statement

The loop statement used here is the while loop. We will use an field called arrived as the loop's control expression. To enable the delay in the periodic repeating process, we should bring the Thread to sleep for a defined time (100 ms). This can be easily implemented by calling the static method of Thread.sleep().

class MobileTask extends Thread
{
    int targetX,targetY,originX,originY,stepX,stepY,blinks;
MobileStation movingStation;
boolean arrived = false; // add this new field in the Class
// ... No change in the Class Constructor public void run() { while (!arrived) {
int movingX = (int) movingStation.getX(); int movingY = (int) movingStation.getY(); if ((movingX == targetX)&&(movingY==targetY)) { removeMobileStation(movingStation); //To be defined in VisualMobileSystem Class textarea.append(movingStation.getID() + " at " + movingX +","+movingY+" released.\n"); movingStation=null; repaint(); this.cancel(); //End the thread execution similar to TimerTask. } else { movingX += stepX; movingY += stepY; if ( stepX == 0 ) movingX = (int) ( ((double)(targetX-originX)/(targetY-originY))*(movingY-originY)+originX); if ( stepY == 0 ) movingY = (int) ( ((double)(targetY-originY)/(targetX-originX))*(movingX-originX)+originY); moveMobileStation(movingStation,movingX,movingY); } try { Thread.sleep(100); //Go to sleep before continuing } catch (InterruptedException e) { //Some codes when it is interupted (leave this empty for this time) } } }
}

Add the cancel() method

The cancel() method does not exists in Thread Class as it is in TimerTask Class. Thus, we should create our own custom cancel() method, and it is simple. We just have to provide the elegant way to exit from the while loop so that the thread is ended (by setting arrived field to true).

class MobileTask extends Thread
{
	// ... The rest of the MobileTask statements

    public void cancel() 
    { 
        arrived = true; 
    }
}

Modifications in mouseReleased(MouseEvent) method

Of course, we should modify this method. We will not use the Timer Class anymore (so you can delete any statements that uses the Timer Class). In the mouseReleased() method of the VisualMobileStation Class, we will replace the timer statement with a MobileTask thread creation and thread execution statement. Detail about how it works have been discussed in Some basics about thread section. Below is the code:

public void mouseReleased(MouseEvent e) 
{ 
     int x = e.getX(); 
     int y = e.getY(); 
//   timer.schedule(new MobileTask(ms,x,y),100,100); // This statement should be deleted
     MobileTask theTask = new MobileTask(ms,x,y);  // creates the MobileTask Thread
     theTask.start(); // Starts the MobileTask Thread to execute the run() method
     target = null; 
     ms    = null; 
     repaint(); 
}

What if.... ?

As described in the Some basics about thread section, besides defining a Class as a SubClass of Thread; in order to define a Thread; we can also use the Runnable Interface. Try to figure out the codes if we would like our MobileTask Class to implement Runnable rather than extends Thread. You may consult with the section for some declarations.


[Contents] [Next] [Previous]