Lecture 16,  Thread Programming

Reading

Slide handouts 4.

Course book: Chapter 16

A more general introduction to the subject can be found in the following trail from Sun: http://java.sun.com/docs/books/tutorial/essential/threads/

It might also be a good idea to take a look at the mentioned methods on the Thread class in the Java API.

Study Guide

The topic of this lecture is thread programming - the concept of being able to run multiple processes simultaneously within a single Java program. The intention is to give you a basic understanding of how threads are used and what the main challenges are. How to program multithreaded systems in a safe and sensible manner is a very big topic and not the scope of this lecture.

When studying for this lecture the important parts to understand are:

·         What is meant by the concept “thread”.

·         In what situations it is advantageous (or necessary) to use threads.

·         How the two different ways of creating threads in Java are used (extending Thread or implementing Runnable)

·         The difference between the methods start() and run() and how they are related.

·         What a daemon-thread is.

·         What does it mean when a thread is blocked.

·         What does a race condition mean?

·         What type of problems might arise when multiple threads access the same objects simultaneously and how the keyword “synchronized” is used to prevent them.

·         What problems the use of “synchronized” might introduce, i.e. deadlocks.

·         How the scheduling of thread-execution can be managed using priorities.

 

Exercises for lecture 4:

Exercise 1. Download SlowPrinter.java. This program currently prints the contents of 3 arrays in a sequential manner. After printing each String it sleeps for a while, so the execution is quite slow done sequentially.

 

SlowPrinter has two methods, one called blockingPrint()and one called nonBlockingPrint(). Currently the method nonBlockingPrint()will throw a  NotImplementedException, to signal that the method is not yet implemented. In this exercise you will need to implement this method.

 

The method blockingPrint()is a blocking method in the sense that a call of  blockingPrint()doesn’t return until the entire contents of the method has been executed. You might say that blockingPrint()borrows the calling methods thread and doesn’t release it until it’s done.

 

The assignment is to implement nonBlockingPrint(), so it does exactly the same as blockingPrint()but in a non-blocking/asynchronous way. (See slide 6).

Your version of nonBlockingPrint()is to start by creating its own thread and then use this thread to print with, so the calling methods thread can return immediately and continue its execution in parallel with the printing.

 

 

Exercise 2. The program JoinExercise.java (download it from the course page) shows how threads can wait for each other using the join()method:

 

(a)    Explain why this program writes what it does.

(b)   Threads can be created either by extending class Thread or by implementing Runnable. If all you need in your thread is to have a run() method you should not extend Thread but implement Runnable. Furthermore using inner classes tends to make the code less readable and classes less reusable. Change the program so:

    • It no longer uses anonymous classes
    • The threads no longer extend Thread, but implement Runnable
    • It still behaves exactly as before

 

 

Exercise 3. In the program SyncExercise.java two threads are requesting the same locks.

 

Explain why the program writes as it does by describing which threads exist and what locks they each hold or wait for:

 

(a)    Shortly after the program has started.

(b)   Approx. 0.5 second after the program has started.

(c)    Approx. 1.0 second after the program has started.

(d)   Approx. 1.5 second after the program has started.

 

(e)    What do you call the situation that arises when the program doesn’t end ?

 

Exercise 4. Download the program Secretary.java

(a)    Change the code to use separate threads for the secretary and a student and a boss giving her assignments at random intervals. Argue for each method you synchronize, and each place you use a synchronized block. Remember that just because the program does as you expect, it is not a guarantee that it is thread safe.

(b)   Enhance the code such that if there are no jobs for the secretary she will wait() for jobs

(c)    Optional ! Enhance the code in such a way that sometimes the boss can give flowers to the secretary. When he does, she will be so happy that she processes her jobs 3 times faster than usual for the next 10 seconds.

 

Exercise 5: This exercise is about creating your own utility class called MyTimer. The intention is for other classes that need to do something at certain time-intervals to reuse the MyTimer class.

 

We will assume that the classes whose instances need to be notified by MyTimer (that is have some method that needs to be called at regular time-intervals) have to implement the following interface:

 

public interface MyTimerListener{

         public void timeAction( );   //The action to be performed

}

 

We will also assume that MyTimer has the following public interface:

 

public class MyTimer{

      public MyTimer(MyTimerListener timerListener, int timeBetweenCalls){

    // Insert code here

 }

}

 

Here timerListener is a reference to the object that needs to have its timeAction( ) method called at a regular intervals specified by the integer parameter timeBetweenCalls (in milliseconds). 

 

(a) Implement the class MyTimer.

 

(b) Now write a test that shows that MyTimer works. You might for instance write two classes that both implement MyTimerListener and have instances of the first class print an X every half second, and instances of the second class print an O every third second.

 

(c) Optional ! Modify the MyTimer class so it takes an argument “repetitions” telling how many times to call the associated MyTimerListener before stopping.

 

(d) Optional ! Write a method MyTimer.waitForStop() that is a blocking call and doesn’t return until the MyTimer instance it is waiting for is done with it’s repetitions. Make sure MyTimer is stopped safely, that is - do not use the deprecated Thread.stop() method !

 

(e) Optional ! Write a method MyTimer.deactivate() that stops MyTimer temporarily from calling timeAction(). MyTimer is to resume calling timeAction() again when someone calls MyTimer.activate() (write this method as well). Do not use the deprecated methods Thread.suspend() and Thread.resume() !