Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon...

55
Supplement to The Design and Implementation of Multimedia Software Multi-Threaded Programs Prof. David Bernstein James Madison University users.cs.jmu.edu/bernstdh D. Bernstein (JMU) Threads www.cs.jmu.edu 1 / 55

Transcript of Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon...

Page 1: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Supplement toThe Design and Implementation of Multimedia Software

Multi-Threaded Programs

Prof. David Bernstein

James Madison University

users.cs.jmu.edu/bernstdh

D. Bernstein (JMU) Threads www.cs.jmu.edu 1 / 55

Page 2: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Introduction

About this Chapter

• Almost everyone that uses a computer today is familiar with theconcept of multi-tasking – “running more than one application ata time”

• This chapter is about multi-threading – allowing each applicationto “perform more than one task at a time”

D. Bernstein (JMU) Threads www.cs.jmu.edu 2 / 55

Page 3: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

A Simple Emergency Vehicle Dispatching System

D. Bernstein (JMU) Threads www.cs.jmu.edu 3 / 55

Page 4: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

Dispatcher – Available Vehicles

import java.util.LinkedList;

public class Dispatcher

{

protected int numberOfVehicles;

protected LinkedList<Integer> availableVehicles;

public Dispatcher(int n)

{

int i;

numberOfVehicles = n;

availableVehicles = new LinkedList<Integer>();

for (i=0; i < n; i++)

{

makeVehicleAvailable(i);

}

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 4 / 55

Page 5: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

Dispatcher (cont.)

public boolean dispatch(String task)

{

boolean ok;

int vehicle;

Integer v;

ok = false;

v = availableVehicles.removeFirst();

if (v == null) ok = false;

else

{

vehicle = v.intValue();

sendMessage(vehicle, task);

ok = true;

}

return ok;

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 5 / 55

Page 6: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

Dispatcher (cont.)

private void sendMessage(int vehicle, String message)

{

// This method would normally transmit the message

// to the vehicle. For simplicity, it now writes it

// to the screen instead.

System.out.println(vehicle+"\t"+message+"\n");

System.out.flush();

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 6 / 55

Page 7: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

Dispatcher (cont.)

public void makeVehicleAvailable(int vehicle)

{

availableVehicles.addLast(new Integer(vehicle));

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 7 / 55

Page 8: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

DailyDispatchHandler

Uses a Dispatcher object to handle a set of “regular” dispatches.

import java.io.*;

import java.util.*;

public class DailyDispatchHandler

{

private Dispatcher dispatcher;

private String fileName;

public DailyDispatchHandler(Dispatcher d, String f)

{

dispatcher = d;

fileName = f;

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 8 / 55

Page 9: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

DailyDispatchHandler.processDispatches()

public void processDispatches()

{

BufferedReader in;

int wait;

long currentTime, lastTime;

String line, message;

StringTokenizer st;

try

{

in = new BufferedReader(new FileReader(fileName));

lastTime = System.currentTimeMillis();

while ((line = in.readLine()) != null)

{

st = new StringTokenizer(line,"\t");

wait = Integer.parseInt(st.nextToken());

message = st.nextToken();

// Wait until the appropriate time before

// dispatching this vehicle

//

while (System.currentTimeMillis()-lastTime

< wait)

{

D. Bernstein (JMU) Threads www.cs.jmu.edu 9 / 55

Page 10: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

DailyDispatchHandler.processDispatches() (cont.)

// Do nothing

}

dispatcher.dispatch(message);

lastTime = System.currentTimeMillis();

}

}

catch (IOException ioe)

{

System.out.println("No daily dispatches "+

"in: "+fileName);

}

catch (NoSuchElementException nsee)

{

System.out.println("Problem in file: "+fileName);

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 10 / 55

Page 11: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

DailyDispatchHandler.start()

public void start()

{

processDispatches();

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 11 / 55

Page 12: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

RealTimeDispatchHandler

Uses a Dispatcher object to handle a set of real-time dispatchesimport java.io.*;

import java.util.*;

public class RealTimeDispatchHandler

{

private Dispatcher dispatcher;

public RealTimeDispatchHandler(Dispatcher d)

{

dispatcher = d;

}

public void processDispatches()

{

BufferedReader in;

String message;

try

{

in = new BufferedReader(

new InputStreamReader(System.in));

while ((message = in.readLine()) != null)

{

dispatcher.dispatch(message);

D. Bernstein (JMU) Threads www.cs.jmu.edu 12 / 55

Page 13: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

RealTimeDispatchHandler (cont.)

}

}

catch (IOException ioe)

{

System.out.println("Problem with the console");

}

}

public void start()

{

processDispatches();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 13 / 55

Page 14: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Motivation

Why We Need Multi-Threading

• The Problem:The RealTimeDispatchHandler can’t start doing any work untilthe DailyDispatchHandler has completed its job

• What’s Needed:A way for multiple objects to use the Dispatcher “at the sametime”

D. Bernstein (JMU) Threads www.cs.jmu.edu 14 / 55

Page 15: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

Specializing the Thread Class

D. Bernstein (JMU) Threads www.cs.jmu.edu 15 / 55

Page 16: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

Specializing the Thread Class - Shortcomings

• Leads people to believe that the ClassForApproachOne object is a“thread of execution”

• A class that extends Thread can’t extend another class

D. Bernstein (JMU) Threads www.cs.jmu.edu 16 / 55

Page 17: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

Implementing the Runnable Interface

D. Bernstein (JMU) Threads www.cs.jmu.edu 17 / 55

Page 18: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

The DailyDispatchHandler Revisited

import java.io.*;

import java.util.*;

public class DailyDispatchHandler implements Runnable

{

private Dispatcher dispatcher;

private String fileName;

private Thread controlThread;

public DailyDispatchHandler(Dispatcher d, String f)

{

dispatcher = d;

fileName = f;

}

public void run()

{

BufferedReader in;

int wait;

String line, message;

StringTokenizer st;

try

{

in = new BufferedReader(new FileReader(fileName));

D. Bernstein (JMU) Threads www.cs.jmu.edu 18 / 55

Page 19: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

The DailyDispatchHandler Revisited (cont.)

while ((line = in.readLine()) != null)

{

st = new StringTokenizer(line,"\t");

wait = Integer.parseInt(st.nextToken());

message = st.nextToken();

try

{

// Sleep the appropriate amount of time

// before dispatching the vehicle. Other

// threads can execute while this one

// is sleeping.

//

controlThread.sleep(wait);

}

catch (InterruptedException ie)

{

// Do nothing

}

dispatcher.dispatch(message);

}

}

catch (IOException ioe)

{

System.out.println("No daily dispatches "+

"in: "+fileName);

D. Bernstein (JMU) Threads www.cs.jmu.edu 19 / 55

Page 20: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

The DailyDispatchHandler Revisited (cont.)

}

catch (NoSuchElementException nsee)

{

System.out.println("Problem in file: "+fileName);

}

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 20 / 55

Page 21: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Getting Started with Threads

The DailyDispatchHandler Revisited (cont.)

public void start()

{

if (controlThread == null)

{

controlThread = new Thread(this);

controlThread.start();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 21 / 55

Page 22: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Understanding Multi-Threading in Java

“At the Same Time”

• Computers with Multiple CPUs or Cores:Multiple threads can be executed at the same time

• Computers with One CPU/Core:Multiple threads take turns

D. Bernstein (JMU) Threads www.cs.jmu.edu 22 / 55

Page 23: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Understanding Multi-Threading in Java

The Thread Lifecycle in Java

D. Bernstein (JMU) Threads www.cs.jmu.edu 23 / 55

Page 24: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Understanding Multi-Threading in Java

Types of Threads

• The daemon status can be changed using the setDaemon() method

• Daemon threads are normally used for background/helperactivities

• A thread should be marked as a daemon only if it can be safelydestroyed at any time (i.e., only if it is safe to stop executing codein that thread at any time)

D. Bernstein (JMU) Threads www.cs.jmu.edu 24 / 55

Page 25: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Understanding Multi-Threading in Java

Interruption

• Every Thread object has an interrupt() method that can beused to set its interrupt status to true

• This method is used to ask a thread to stop what it is currentlydoing

• If you want to write a method that can be “cancelled” you need toinclude code that checks the interrupt status periodically using theisInterrupted() method in the Thread class

D. Bernstein (JMU) Threads www.cs.jmu.edu 25 / 55

Page 26: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Tracing a Multi-Threaded Application

A Tracing Example

public class SlasherDriver

{public static void main(String[] args)

{Slasher plus, slash;

1 slash = new Slasher();

6 slash.setCount(3);

8 slash.start();

10 plus = new Slasher("+");

14 plus.setCount(2);

16 plus.start();

}}

public class Slasher implements Runnable

{private int count;

private String symbol;

private Thread controlThread;

public Slasher()

{2 this("/");

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 26 / 55

Page 27: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Tracing a Multi-Threaded Application

A Tracing Example (cont.)

public Slasher(String symbol)

{3 11 this.symbol = symbol;

4 12 count = 0;

5 13 controlThread = new Thread(this);

}

public void run()

{A C E G for (int i=0; i<count; i++) a c e

{B D F System.out.print(symbol); b d

}}

public void setCount(int count)

{7 15 this.count = count;

}

public void start()

{9 17 controlThread.start();

}}

D. Bernstein (JMU) Threads www.cs.jmu.edu 27 / 55

Page 28: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Race Conditions

A Potential Problem

• The Issue:Conflicts can arise when more than one thread is using the sameobject

• An Example:Suppose two threads are both using the same Dispatcher objectand there is only one vehicle in the queue

D. Bernstein (JMU) Threads www.cs.jmu.edu 28 / 55

Page 29: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Race Conditions

A Potential Problem (cont.)

public boolean dispatch(String task)

{

boolean ok;

int vehicle;

Integer v;

ok = false;

if (availableVehicles.size() > 0)

{

v = availableVehicles.removeFirst();

vehicle = v.intValue();

sendMessage(vehicle, task);

ok = true;

}

else

{

ok = false;

}

return ok;

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 29 / 55

Page 30: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Race Conditions

Race Conditions

• Defined:Code that causes the correctness of a computation to depend on therelative timing of different threads

• This Example:A check-then-act condition

D. Bernstein (JMU) Threads www.cs.jmu.edu 30 / 55

Page 31: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Race Conditions

Race Conditions (cont.)

An Example with a Read-Modify-Write Condition:

public int getNextIndex(){

return ++index;}

The expression ++index actually performs three operations – load thevalue, increment the value, and store the value

D. Bernstein (JMU) Threads www.cs.jmu.edu 31 / 55

Page 32: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Synchronization

“Concurrency Protection” Objects

• In Java, every object (and class) has a monitor (or an intrinsiclock)

• When a thread of execution reaches a synchronized block ormethod it attempts to acquire the relevant monitor

• A thread of execution can only enter a synchronized method/blockif it can acquire the relevant monitor and only one thread canacquire a monitor at a time

D. Bernstein (JMU) Threads www.cs.jmu.edu 32 / 55

Page 33: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Synchronization

A Synchronized Method

public synchronized boolean dispatch(String task)

{

boolean ok;

int vehicle;

Integer v;

ok = false;

v = availableVehicles.removeFirst();

if (v == null) ok = false;

else

{

vehicle = v.intValue();

sendMessage(vehicle, task);

ok = true;

}

return ok;

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 33 / 55

Page 34: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Synchronization

Is the Problem Fixed?

• The Good:The entire method now behaves as if it were atomic

• The Bad:There are other methods in the class that change state (i.e., boththe dispatch() method and the makeVehicleAvailable() methodchange the attribute availableVehicles)

D. Bernstein (JMU) Threads www.cs.jmu.edu 34 / 55

Page 35: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Synchronization

Another Synchronized Method

public synchronized void makeVehicleAvailable(int vehicle)

{

availableVehicles.addLast(new Integer(vehicle));

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 35 / 55

Page 36: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Liveness Failures

Liveness Failures

• Defined:A state in which an application/algorithm is unable to make anyprogress

• Types:Deadlock - when two or more threads are waiting on conditions thatcan’t be satisfied

Livelock - a thread can’t make progress because it repeatedlyattempts an operation that fails (e.g., you first, no you first)

D. Bernstein (JMU) Threads www.cs.jmu.edu 36 / 55

Page 37: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Possible Performance Failure

• The Problem:The sendMessage() methods is being executed in either theDailyDispatchHandler object’s thread or in the main thread andthe thread might block

• A Better Approach:Have the dispatch() method in the Dispatcher class returnalmost immediately and have the messaging code execute in anotherthread

D. Bernstein (JMU) Threads www.cs.jmu.edu 37 / 55

Page 38: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Adding a “Task Queue”

public void dispatch(String task)

{

// Add a task to the queue

tasks.add(tasks.size(), task);

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 38 / 55

Page 39: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Adding a Thread

import java.util.*;

public class Dispatcher implements Runnable

{

private int numberOfVehicles;

private List<Integer> availableVehicles;

private List<String> tasks;

private Thread dispatchThread;

public Dispatcher(int n)

{

int i;

numberOfVehicles = n;

availableVehicles =

Collections.synchronizedList(new LinkedList<Integer>());

tasks =

Collections.synchronizedList(new LinkedList<String>());

for (i=0; i < n; i++) makeVehicleAvailable(i);

// Start the thread

dispatchThread = new Thread(this);

dispatchThread.start();

D. Bernstein (JMU) Threads www.cs.jmu.edu 39 / 55

Page 40: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Adding a Thread (cont.)

}

private void sendMessage(int vehicle, String message)

{

// This method would normally transmit the message

// to the vehicle. For simplicity, it now writes it

// to the screen instead.

System.out.println(vehicle+"\t"+message+"\n");

System.out.flush();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 40 / 55

Page 41: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Modifying run()

public void run()

{

while (true)

{

processPendingDispatches();

try

{

dispatchThread.sleep(1000);

}

catch (InterruptedException ie)

{

// Shouldn’t be interrupted. If it is,

// just continue.

}

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 41 / 55

Page 42: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Modifying processPendingDispatches()

private void processPendingDispatches()

{

int vehicle;

Integer v;

String task;

while ((availableVehicles.size()>0) && tasks.size()>0)

{

v = availableVehicles.remove(

availableVehicles.size()-1);

task = tasks.remove(tasks.size()-1);

vehicle = v.intValue();

sendMessage(vehicle, task);

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 42 / 55

Page 43: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

Considering this Design

• It is troubling to be putting the dispatchThread object to sleepfor an arbitrary amount of time

• It would be better for the dispatchThread to wait until there areeither new tasks to be dispatched or new vehicles to dispatch themto

D. Bernstein (JMU) Threads www.cs.jmu.edu 43 / 55

Page 44: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Better Design

import java.util.LinkedList;

public class Dispatcher implements Runnable

{

private int numberOfVehicles;

private LinkedList<Integer> availableVehicles;

private LinkedList<String> tasks;

private Thread dispatchThread;

private final Object lock = new Object();

public Dispatcher(int n)

{

int i;

numberOfVehicles = n;

availableVehicles = new LinkedList<Integer>();

tasks = new LinkedList<String>();

for (i=0; i < n; i++)

{

makeVehicleAvailable(i);

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 44 / 55

Page 45: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Better Design (cont.)

dispatchThread = new Thread(this);

dispatchThread.start();

}

private void sendMessage(int vehicle, String message)

{

// This method would normally transmit the message

// to the vehicle. For simplicity, it now writes it

// to the screen instead.

System.out.println(vehicle+"\t"+message+"\n");

System.out.flush();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 45 / 55

Page 46: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Better Design (cont.)

public void dispatch(String task)

{

synchronized(lock)

{

// Add a task to the queue

tasks.addLast(task);

// Start the processing

lock.notifyAll();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 46 / 55

Page 47: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Better Design (cont.)

public void makeVehicleAvailable(int vehicle)

{

synchronized(lock)

{

// Put the vehicle in the queue

availableVehicles.addLast(new Integer(vehicle));

// Start the processing

lock.notifyAll();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 47 / 55

Page 48: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Performance Failures

A Better Design (cont.)

public void run()

{

while (true)

{

synchronized(lock)

{

processPendingDispatches();

try

{

lock.wait();

}

catch (InterruptedException ie)

{

// Shouldn’t be interrupted. If it is,

// just continue.

}

}

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 48 / 55

Page 49: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Starting and Stopping Threads

Considering the Improved Design

• The thread that is handling the dispatches never dies since itnever “drops out of” the run() method

• This problem can be corrected by adding a boolean attributenamed keepRunning and modifying the run()

D. Bernstein (JMU) Threads www.cs.jmu.edu 49 / 55

Page 50: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Starting and Stopping Threads

A Still Better Design

public void run()

{

while (keepRunning)

{

synchronized(lock)

{

processPendingDispatches();

try

{

lock.wait();

}

catch (InterruptedException ie)

{

// The stop() method was called in

// another thread

}

}

}

dispatchThread = null;

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 50 / 55

Page 51: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Starting and Stopping Threads

A Still Better Design (cont.)

public void stop()

{

synchronized(lock)

{

keepRunning = false;

// Interrupt the thread in case it

// is waiting

dispatchThread.interrupt();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 51 / 55

Page 52: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Starting and Stopping Threads

A Still Better Design (cont.)

public void start()

{

if (dispatchThread == null)

{

keepRunning = true;

dispatchThread = new Thread(this);

dispatchThread.start();

}

}

D. Bernstein (JMU) Threads www.cs.jmu.edu 52 / 55

Page 53: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Volatile Attributes

A Problem Remains

• The stop() method is going to be executed in a different threadthan the run() method and they both use the keepRunningattribute

• This causes a problem because Java does not ensure that changesto attributes that are made in one thread propogate to otherthreads in the way you would expect (i.e., for performancereasons, values can be “cached” in such a way that they arehidden from other threads)

D. Bernstein (JMU) Threads www.cs.jmu.edu 53 / 55

Page 54: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Volatile Attributes

Volatile Attributes

• Volatile attributes are, in essence, attributes that are sharedacross multiple threads

• A “load” of a volatile attribute in any thread always returns themost recent “store” performed in any thread

D. Bernstein (JMU) Threads www.cs.jmu.edu 54 / 55

Page 55: Multi-Threaded Programs...Understanding Multi-Threading in Java Types of Threads † The daemon status can be changed using the setDaemon() method † Daemon threads are normally used

Volatile Attributes

Volatile Attributes (cont.)

private volatile boolean keepRunning;

D. Bernstein (JMU) Threads www.cs.jmu.edu 55 / 55