Software System Components 2 - Year 2, Semester 2, Week 7

Concurrency - Dr Steve Vickers

1: Threads

A Java program always consists of several tasks being done at the same time, or concurrently. This is achieved by a very clever use of the processor chip. Although it can only execute code for a single task at any given time, the code being executed is sometimes for one task, sometimes for another, and sometimes for the operating system that coordinates them. They are carefully interleaved to give the illusion of several pieces of code being executed at once.

Concurrency sets some of the most dangerous traps in all of programming. Concurrent tasks can cooperate successfully thousands of times, and then just once in a while interfere in such a way that neither quite does what its code says it should. We shall see much more this next week. These problems are a nightmare to debug. It is hard to relate the fault to what the code says, and because it is sporadic, it is also very hard to reproduce. In critical software such faults can cause lost money or even lost lives. The good news is that there are safe programming techniques for eliminating them. You cannot consider yourself a competent software engineer unless you are aware of the concurrency dangers and know how to avoid them.

In the Java system the concurrent tasks are called threads. There will be different threads present anyway, but you can also create your own.

At the end of this week's lectures you should know -

Some threads in action

I use examples from the turtles package. If you did not do the year 1 module "Software Workshop 1", you can find instructions for installing and using the turtles at the end of these notes.
Example: OffCircles
In this example (file OffCircles.java), the main method repeatedly draws circles, but with a randomness in the side length that distorts their shape. Thus you see lots of "off-circles".

public static void main(String[] args) {
    Turtle theTurtle = new Turtle();
    new TurtleGUI(theTurtle);
      
    while (true){
        theTurtle.move(Math.random()*5);
        theTurtle.turn(1);
    }
}

The point to note is that while it is drawing off-circles, you can also control the turtle with its buttons.
Example: OffCirclesGo
This uses files OffCirclesGo.java and GoFrame.java. It is very similar to OffCircles, except that the off-circles are drawn by a listener on a button. The intention is that you press the button to start drawing the off-circles.

Why does it not work? How might you try to debug it?
Example
Take OffCircles.java, and put "assert false;" just before the while loop. When you run it, it shows an exception report

Exception in thread "main" java.lang.AssertionError

This is roughly as expected, except that the turtle GUI is still working. You can use the buttons to control the turtle, although there are no off-circles. How can that be? Doesn't the exception stop everything?
Example
Do the same with OffCirclesGo.java. This time the exception report is

Exception in thread "AWT-EventQueue-0" java.lang.AssertionError

Two different threads

The exception reports tell us about two different threads, "main" and "AWT-EventQueue-0".

A thread is a single flow of control through a program. If you follow through the statements that are executed, into methods as they are called and then back out of them on return, then you are following a thread.

When you run a Java program, a thread is created to start executing the main method and all the methods called by it. Naturally enough, this is the "main" thread.

But a Java program can have more than one thread - it can be multithreaded. The threads then run "concurrently". This means they look as though they are running at the same time as each other, though more usually the Java system is cleverly interleaving them, running a little bit of one, then a little bit of another, and so on.

Some of the threads are set up automatically by the system to perform special tasks, while others might be set up by explicit code in your program. (We shall soon see how to do that.)

Amongst the automatic system threads one of the most important is the event dispatch thread, "AWT-EventQueue-0". This has the job of running all GUI code including the paint methods for screen components, and the actionPerformed methods for buttons and so on.

We now have the answer to the off-circles question. In OffCircles, it is the main thread that executes the infinite loop of  move and turn methods to draw the off-circles. Concurrently, the event dispatch thread paints the turtle and also looks after the buttons, executing the move and turn methods for them. In OffCirclesGo the event dispatch thread executes the actionPerformed method in response to the Go button, and so goes into the infinite loop. After that, the event dispatch thread never gets a chance to execute any paints or any other actionPerformed methods. So although the turtle is in fact doing all the off-circles, nothing is seen on the screen, and the buttons don't respond. The infinite loop has "hijacked" the event dispatch thread.

In fact this is one very common use for setting up your own threads - so as not to hijack the event dispatch thread. A good rule is never to let the event dispatch thread do anything that might take a long time.

Setting up your own threads

To set up a thread you normally need two different objects. One, the thread itself, knows how to execute code, and the other, the run-object, knows what code to execute.

The thread is an instance of Java.lang.Thread. It has all the features that enable it to take part in the operating system as a flow of control.

However, you also want to specify the code that it will excute. You can only write code as part of a method in a class, and the code for a thread is written as a method called run. You then create the run-object as an instance of this class.

The way the thread and the run-object work together is a bit like the way a button works with an action listener, and again there is an interface involved. It is java.lang.Runnable:

public interface Runnable {
    public abstract void run();
}

The general scheme is this.
  1. Write a class, implementing Runnable, whose run method is the code you want to be executed by a thread.
  2. Create an instance of that class. This is the run-object.
  3. Create an instance of Thread, using the run-object as constructor parameter.
  4. Call the start() method on the thread. This starts the thread executing run() on its run-object.
A beginner's mistake: Don't confuse start() with run(). If you call the run method on the thread, it will execute the right code but on the wrong thread.  It won't start the new thread, but will continue executing on the old one.
Example: OffCirclesGo corrected
Here (file OffCirclesGoGood.java) is a correct version of the class OffCircler for the OffCirclesGo example. An instance of OffCircler is the action listener for the Go button. Instead of just executing the off-circle loop on the event dispatch thread, we create a new thread to do it. That means the event dispatch thread can go back to painting and handling button presses.

class OffCircler implements ActionListener {
    private Turtle theTurtle;
   
    /**
     * Constructor initializing theTurtle from parameter.
     * @param theTurtle value for theturtle field.
     */
    public OffCircler(Turtle theTurtle) {
        this.theTurtle = theTurtle;
    }
   
    /**
     * Draw off-circles for ever on theTurtle.
     * @param e event parameter from action event (not used)
     */
    public void actionPerformed(ActionEvent e) {
        Thread t = new Thread (new OffCirclerRunnable());
        t.start();
    }
   
    private class OffCirclerRunnable implements Runnable {
        public void run() {
            while (true){
                theTurtle.move(Math.random()*5);
                theTurtle.turn(1);
            }
        }
    }
}

We put the off-circle loop in the run method for OffCircleRunnable. In actionPerformed, we create a new OffCirclerRunnable instance, and make it the constructor parameter for a new thread t. Then we start t.

Inner classes

We made the class OffCirclerRunnable private, and defined it inside the class OffCircler. It is called an inner class in OffCircler. Runnable classes don't have to be defined like that, but in this case it has an interesting advantage. Its methods have access to the field theTurtle in OffCircler. (Technically, every instance of OffCirclerRunnable is attached to an instance of OffCircler and has access to its fields.)
Unassessed exercise
Find a simpler solution in which the action listener is also the run-object. For this you won't need a separate class OffCirclerRunnable. Instead, OffCircler will have to implement Runnable.

Thread states

There are various states a thread may be in.
You can tell whether a thread is alive or not by calling the isAlive method on it.
There may be many runnable threads, but normally only one at a time can be actually running - for the simple reason that the computer may have only one processor chip.

However, there are also various reasons why an alive thread might not be runnable. We shall see those later. It might have put itself to sleep for a fixed time, or it might be waiting for something to be done by other threads. Such a thread is suspended.

Thread pools

Threads consume a lot of system resources. Each thread uses a lot of memory, and creating and destroying threads takes a lot of time. This can be a big overhead if you have lots of small tasks that need to be run on separate threads. Therefore it is desirable to be able to limit the total number of threads, and to maximize the use of each thread once it has been created.

"Thread pools" are a way to do this. A thread pool keeps a fixed set of threads that are available for running a succession of short tasks, each presented as a run- object (i.e. an instance of a class that implements Runnable). Think of the threads in the pool as being like counter staff in a post office, and the run-objects as being like customers, each with its own task to perform. The threads take on any tasks that come along, and when all the threads are busy the tasks wait in a queue.

There are various ways to create thread pools and similar gadgets, using classes in the package java.util.concurrent. We shall describe one of the simplest.

To create a thread pool with nThreads threads in it, use this static factory method from java.util.concurrent.Executors.
public static ExecutorService newFixedThreadPool(int nThreads)
Its result is the thread pool.  Once you have your thread pool, there are many methods you can call on it. Here are the most useful.

void execute(Runnable command)
The parameter "command" is task to be submitted to the pool. If any threads are available to run it, one of them does so. Otherwise the task waits in a queue until a thread is free. Throws RejectedExecutionException if the thread is shut down (see below).

void shutdown()
Shuts the pool down. No new tasks will be accepted, though tasks still being run, or in the queue, will be completed.

List<Runnable> shutdownNow()
Shuts the pool down, aborts the tasks waiting to be run, and interrupts those being run. ("Interrupts" will be explained under Stopping a thread. The returned result, of type List<Runnable>, is a list of the tasks that were waiting to be run. But often you can just ignore that and treat shutdownNow as though it is void.)
Example: CirclesPool
The class CirclesPool draws circles with a turtle. The main method constructs a thread pool with just one thread. Then it reads in radii of circles from an input frame, and submits one task to the pool for each circle. When it reads a negative radius, it will shut down the pool and stop the main thread. Here is the central part of the main method.

ExecutorService pool = Executors.newFixedThreadPool(1);

boolean stopping = false;
while (!stopping) {
    double radius = theInputFrame.getDouble();

    if (radius > 0) {
        pool.execute(new Circler(theTurtle, radius));
    } else {
        pool.shutdown();
        stopping = true;
    }
}

It uses input frames, which are provided with the turtle graphics package. Circler is a class that implements Runnable. Its run method draws a circle on the given turtle with the given radius. We shall look at it more closely later.

When you execute CirclesPool, quickly type in a few radii, for example 10, 20, 30, 40, 50, and then type in -1. This will create 5 separate Circler run-objects that get submitted (by execute) to the thread pool. The single thread in the pool will run them one after the other. When you enter -1, the pool will shut down. It won't accept any more tasks, but it will complete all the circles that are already waiting.

If you replace shutdown by shutdownNow, the shutdown behaviour is more drastic. The current circle is finished as quickly as possible and any other ones still waiting are omitted. We shall see how this works later.

Stopping a thread

The only safe way to stop a thread is for it to stop itself. This is because it may be in the middle of complex operations that have to be cleaned up.

In every run method you should consider how it can stop.

Call interrupt() on a thread to signal that it should stop itself. The effect of this is to "set the interrupt status" of the thread, something that the run method can detect.

There are two main ways the run method can check the interrupt status. The simplest is by calling Thread.interrupted(). This returns a boolean result to say whether or not the interrupt status (of the currently executing thread) is set. At the same time, it also resets the interrupt status, so calling Thread.interrupted() a second time will return false (unless there has meanwhile been yet another call of interrupt()).
Example: OffCirclesGoStop1
Here (in file OffCirclesGoStop1.java) is one way to rewrite the run method of OffCirclesGo so that it stops if the thread is interrupted. The idea is completely simple. instead of looping forever (while (true)), we loop until an interrupt is detected.

public void run() {
   while (!Thread.interrupted()){
       theTurtle.move(Math.random()*5);
       theTurtle.turn(1);
   }
}

Remember! Whenever you write a run method, consider how it can detect when the interrupt status is set, and stop. We have now done that with our off-circles run.

Now we have rewritten run so that it can stop, we can use that in other parts of the program. Here is a version where we can stop the thread by pressing the Go button a second time. (Hence while the thread is running, the "Go" button means "stop". Sorry about that. If you are used to pressing "Start" to make Windows shut down, you should not find this too confusing.) We rewrite actionPerformed so that if the thread is running, it gets interrupted. Since actionPerformed has ot remember what the thread is from one call to the next, we make the thread a field of OffCircler. We set this field to null when there is no thread.

private Thread theThread = null;

public void actionPerformed(ActionEvent e) {
    if (theThread == null) {
        theThread = new Thread (new OffCirclerRunnable());
        theThread.start();
    } else {
        theThread.interrupt();
        theThread = null;
    }
}

Thread.sleep

The second way to detect the interrupt status looks more complicated, but is often very convenient.

The static void method Thread.sleep(long millis) suspends the current thread ("sends it to sleep") for the given number of milliseconds. (Note: "long" is the type for double-length integers. A long integer is stored in 64 bits, instead of 32 for int.) During that time it is not runnable, but waiting.

However, if you try to use it on its own in a method, you get a compile error. This is because sleep throws a checked exception InterruptedException. (Remember that "checked" means you must either put the call of sleep in a try-catch statement, or declare your own method as throwing the same exception. The only unchecked exceptions are those that subclass Error or RuntimeException.)

Beginners' error: It is tempting to squash the exception by catching it but not handling it, e.g.

try {
    Thread.sleep(1000);  //sleep 1 second
} catch (InterruptedException e) {
}

Don't do this with checked exceptions. The reason they were designed to be checked is that you are expected to do something about them when they arise. If you squash them, then - to quote Joshua Bloch in "Effective Java" - you are not only ignoring the fire alarm, but also turning it off so nobody else knows it rang.

Why does sleep throw this exception? It is part of making sure the thread knows if interrupt() is called on it. If a thread is asleep, it cannot be calling Thread.interrupted() to check the interrupt status. Therefore -
In each case, an InterruptedException is thrown and the interrupt status is reset. (It does not need to be set any more, because the InterruptedException means the thread now knows about the interrupt.)

Dealing with an InterruptedException in the run method

Remember, you got an InterruptedException because some other thread wants you to stop and called interrupt() on you. If you know what to do to stop, then you should catch the exception and arrange the stop. This generally applies if you call sleep in the run method.
Example: OffCirclesGoStop2
Here is a modification of OffCirclesGoStop1 in which the off-circles are slowed down with sleeps.

public void run() {
   boolean stopped = false;

   while (!stopped){
       try {
           Thread.sleep(50);
       } catch (InterruptedException e) {
           stopped = true;
       }
       theTurtle.move(Math.random()*5);
       theTurtle.turn(1);
   }
}

This pattern, with a boolean variable to control stopping, is very common in properly written run methods, and you should learn it.

Note how we don't need to call interrupted() any more. Calling sleep on every repetition allows the method to find out if the interrupt status is set.

Dealing with an InterruptedException in other methods

When you call sleep in methods other than run, quite often you don't know how to stop the thread - because you don't know what threads might call the method. In this case you need to think more carefully.

In the situation where the InterruptException arises, ask yourself, Can the method still perform its usual task?

If not, then the method should throw an exception - that is what exceptions are for. Usually you just declare the method as throwing InterruptedException, and then you don't need a try-catch round Thread.sleep(). Make sure your Javadoc explains when the exception is thrown.

If the method can successfully perform its usual task, despite the InterruptedException, then it is usually more convenient not to rethrow the exception. If you don'tyou must make sure the interrupt status is set again. This is so that when control returns to the run method it can detect the interrupt. Use the following code.

try {
    Thread.sleep(...);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

The static method Thread.currentThread() returns a reference to the thread currently executing. This might look a bit odd - the current thread is interrupting itself. It is really saying, "I know I must stop, but I don't know what to do about it yet. I should know when I'm back in the run method. Meanwhile, I must leave a reminder note to myself."
Example: Circler
We saw CirclesPool before but did not look closely at its Circler class. Here is its run method. It uses Thread.sleep.

public void run() {
    for (int i = 0; i < STEPS; i++) {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); //no more sleeps
        }
        theTurtle.move(stepSize);
        theTurtle.turn(360.0/STEPS);
    }
}

Note that run cannot throw InterruptedException, because the Runnable interface does not declare it to do that. Hence we must use try - catch. There is a design decision in the way we do it here. When an interrupt is received, we call interrupt again. The effect is that the circle still gets drawn but there are no more sleeps. (Each time sleep is called, it throws InterruptedException.) Hence the circle is finished off quickly.

There are alternatives to calling interrupt in the catch-block. This next one would stop immediately without completing the circle.

} catch (InterruptedException e) {
    return;
}

This one would squash the exception and the circle would be completed as normal.

} catch (InterruptedException e) {
}

Squashing an exception is generally a bad idea, for the reasons already mentioned. But in this case it might be reasonable because we know the run method is going to terminate anyway.

Example
Suppose you have a graphics component with a method animate() that shows an animation, drawing a sequence of images over a period of time. It might use sleep for the timing. How do you deal with an InterruptedException? You have to decide whether to abort the animation or complete it.

First alternative: aborts the animation if thread is interrupted. This is more drastic but quicker.

/** display animation.
 * ...
 * throws Interrupted Exception if thread is interrupted
 *    - and then animation is aborted.
 */
public void animate()
   throws InterruptedException
{
    ...
    Thread.sleep(...);
    ...
}

Second alternative: completes the animation. This is easier but takes longer to stop the thread.

public void animate()
{
    ...
    try {
        Thread.sleep(...);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    ...
}

Deprecated methods and stop()

The Thread class has a method stop() that forces the thread to stop executing. So why don't we just use that? The answer is that stop is deprecated. This means that it is not recommended, and may (in theory) be withdrawn from future versions of Java. The reason is for this is that stop is unsafe. While a thread is updating an object, it may temporarily put the object in a bad state with its invariants broken. That is normally OK because the thread is going to repair everything before it finishes. But if the the thread is stopped in the middle of the update, then the object is left permanently in the bad state. In fact there is no safe way to force a thread to stop. You have to rely on its cooperation. That is why we use interrupt.

Next week

A thread keeps its own return stack and its own values of the actual parameters and local variables in the methods. However, it does not keep its own values of object fields. Those values are stored by the objects, not by the threads. For example, in OffCircles two threads were calling methods on one single turtle. That turtle had to look after the values of its fields, and one of the central problems is how it can do that when different threads are concurrently accessing those fields and sharing their values. Next week we shall see just how bad the problem is and what can be done about it.

Summary

Notes

Turtle graphics

If you took the year 1 module "Software Workshop 1" you will know this already.

The turtle graphics can be seen as an applet here.

It is in a Java package fyw.turtles. To use it from netBeans you will need to link the turtles library into your netBeans project, presumably the project for your Concurrency (weeks 7-9) exercise.

Linking in the turtles library

For your exercises you will need to use the turtle graphics packages that we have already written for you. You do not need to look at the source code or understand it at all. However, you need to add it to the fywExercises library so that netBeans knows where to find it for your programs. Proceed as follows.
  1. Make sure you can see your concurrency project in the Project pane, with "Libraries" underneath (after "Source Packages" and "Test Packages").
  2. Right click on "Libraries", and select "Add JAR/Folder ...". (JAR stands for Java ARchive, and is a collection of Java files bundled up into one. But we are adding a folder.)
  3. You should get a window "Add JAR/folder". In it you must browse for a folder called /bham/common/java/packages/fyw/javalib. You are at the right place when the "File Name" box says "javalib".
  4. Click "Open".
If you open up "Libraries" under your concurrency project, you should see two libraries. One is called "JDK 1.5 (Default)" and is the standard Java library. The other is called "/bham/common/java/packages/fyw/javalib". If you open that up, you will see a number of packages including "fyw.turtles" and "fyw.autoevent". If you see those then you have successfully linked in the turtles library. You should also be able to see the source code, if you are interested.

You should also be able to copy the turtles library onto your own computer.

Using the turtle from Java

The turtle needs two objects created. The turtle itself, without any GUI, is of class Turtle. You will also need some GUI to view and control the turtle. This is of class TurtleGUI, and its constructor takes as parameter the turtle to be installed in the GUI. Typically you write

Turtle theTurtle = new Turtle();
new TurtleGUI(theTurtle);


in your main method. Once this is done you can control the turtle either from the GUI buttons or by Java method calls on theTurtle. Here is a list of the principle methods, instance methods from class Turtle.

public void move(double distance)
Move turtle ahead through given distance.

public void turn(double angle)
Turn turtle through given number of degrees (clockwise).

public void restart()
Clear turtle pane and move turtle to its starting position.

public void penUp()
"Lift pen up", so that turtle does not leave a line when it moves.

public void penDown()
"Put pen down", so that turtle does leave a line when it moves.

Input frames

Input frames are a convenient way to input numbers (int or double) into a program. The class InputFrame is included in the package fyw.turtles. An input frame has its own window on the screen, with an editable text area and a button. When the program needs a number from it, it calls either getInt() or getDouble(). The user then types in the number and presses either enter or the button. The input frame checks the format (if it is invalid the user has to correct it) and returns the value.

Assert statements

An assert statement takes the form

assert  boolean expression ;

When the program is run, if the boolean expression evaluates to false then an AssertionError is thrown. This is intended as a debugging aid. Programs should be designed so that their assert statements never do throw an error. Usual practice is to leave them in the final source code as comments, but turn off the assertion checking to speed up the program's execution.

To ensure that assertion checking is turned on, do the following.
  1. Right click on the project icon.
  2. Select Properties and click the Run category.
  3. Ensure that the "VM Options" box (virtual machine options) has "-ea" typed in it.
This has the effect that when netBeans runs a program, it does it as though with "java -ea ...". The -ea option is for "enable assertions".

Anonymous inner classes

Inner classes can be taken a step further, and used "anonymously". Here is an example equivalent to the above code for actionPerformed.

public void actionPerformed(ActionEvent e) {
    Thread t = new Thread (new Runnable() {
        public void run() {
            while (true){
                theTurtle.move(Math.random()*5);
                theTurtle.turn(1);
            }
        }
    });

    t.start();
}

"new runnable()" is usually quite wrong - you can't instantiate an interface. But here we are instead creating an new instance of an anonymous class that implements Runnable by having the given definition for run.

This use of anonymous inner classes is quite often used for run-objects, and it also works well for event listeners.

Extending Thread

I described how to set up a thread using two separate objects: one of class Thread, and a separate run-object whose class implements Runnable.

There is an alternative way that you often see described (for instance, in the API). This is to use a single object whose class extends Thread and implements Runnable. This can be more convenient in a simple one-off program. However, for large pieces of software the technique with a separate run object is much more flexible. That is because there are really two independent questions: What code do you want to run? and How do you want to run it? The run-object looks after the first question, the thread looks after the second. If you keep them separate then you can vary the two answers independently. For instance, it is simple to replace a thread by a thread pool.

I recommend you to use run objects and not extend Thread.

ThreadPoolExecutor class

We saw thread pools created by a factory method, Executors.newFixedThreadPool, and their methods were specified by an interface, ExecutorService. You might wonder why there wasn't a class for thread pools, with its own constructors and methods. In fact there is, and it is ThreadPoolExecutor (and it implements ExecutorService). When you use newFixedThreadPool it is quite likely that the thread pool it creates has class ThreadPoolExecutor, although this is not guaranteed by the API. However, ThreadPoolExecutor has a lot of configurable features and can be quite complicated. Using newFixedThreadPool and ExecutorService is a simple way to get a basic thread pool in a standard default configuration.