CS 4773 Object Oriented Systems Threads and Thread Synchronization


Topics for today:

Threads

There are two main ways to use threads in Java:

When you declare a Thread variable with
Thread ping
the variable is initially null.

If an class implements Runnable it must have a run method. Executing:
ping = new Thread(this)
creates a new thread which can execute the run method of the class. The thread can be started with its start method:
ping.start();
At this point the thread is in its active state. It remains active until it is stopped or it completes execution of its run method.


Ping Pong Application

PingPong.java is a thread that prints out a word a given number of times with a given delay. It also shows the number of active threads.

PingPongTest1.java is an application that just starts two copies of PingPong.

Using join

Join suspends the caller until the thread has completed.

The PingPongTest2 application waits for each thread to complete and then prints a message. It also has a method which shows the threads.


Thread States Note: neither suspend nor stop should be used.

Synchronization in Java

Synchronization is done in Java using monitors.

Each instance of a class has its own monitor with one (anonymous) condition variable.

Recall that a monitor is a compiler construct which allows only one process to be active (own the monitor) within the protected methods of the monitor.

In Java, by default, no methods of the object are protected. You can protect methods by using the synchronized key word.

How to own a monitor of an object

        synchronized (obj) {
           code goes here
        }
The second method is unusual.

Protecting a critical section

If multiple threads are going to modify an ArrrayList, all modifying methods must be synchronized:

   ArrayList list = new ArrayList();

   public synchronized void insertElement(Item a) {
      list.add(a);
   }

   public synchronized void removeElement(Item a) {
      list.remove(a);
   }

   public synchronized void showIt() {
      for (Item it : list)
         System.out.println(it.toString());
   }
Note that the last one needs to be synchronized also so that the list is not changed while it is being accessed.

Here are some of the important methods related to thread synchronization:

Waiting for a variable to change (without busy waiting)

   public synchronized void test1() {
      while (count == 0)
         try {
            wait();
         catch (InterruptedException e) {}
      ...
   }
 
   public synchronized void test2() {
      ...
      count++;
      if (count == 1)
         notify();
   }
Note that the two methods must be in the same object (same monitor) and executed by different threads.

AWT events and threads

When an event such as a mouse click or button push occurs, and event handler is called by the thread that handles AWT events. When a button is pushed it might call actionPerformed in a class.

In general, this should only use the CPU for a short time, or other AWT events will be blocked.

The usual method for handling this is to have the actionPerformed just set a variable and wake up or create a thread to handle the action.

Look at the ButtonThread example.