CS2_H_Ch21_Multithreading

Document Sample
CS2_H_Ch21_Multithreading Powered By Docstoc
					CHAPTER 21

Multithreading
           CHAPTER GOALS
• To understand how multiple threads can execute
  in parallel

• To learn how to implement threads

• To understand race conditions and deadlocks

• To be able to avoid corruption of shared objects
  by using synchronized methods

• To be able to use threads for programming
  animations
                 Threads
• A thread is a program unit that is executed
  independently of other parts of the program

• The Java Virtual Machine executes each
  thread in the program for a short amount of
  time

• This gives the impression of parallel
  execution
        Steps to Running a Threads
• Implement a class that extends the Thread class
• Place the code for your task into the run method
  of your class
• Create an object of your subclass
• Call the start method of your class to start the
  thread
• When a Thread object is started, the code in its run
  method is executed in a new thread
         GreetingThread Outline
• A program to print a time stamp and "Hello World"
  once a second for ten seconds
   public class GreetingThread extends Thread
   {
     public void run()
     {
          //thread action
          . . .
     }
     //variables used by the thread action
    . . .
   }
Thread Action for GreetingThread

    • Print a time stamp

    • Print the greeting

    • Wait a second
                     GreetingThread
• We can get the date and time by constructing Date
  object
    Date now = new Date();

•     To wait a second, use the sleep method of the Thread
    class
    sleep(milliseconds)

•     A sleeping thread can generate an
    InterruptedException
     o Catch the exception
     o Terminate the thread
     GreetingThread run   method
public run()
{
      try
      {
           //thread action
      }
      catch (InterruptedException exception)
      {
           //cleanup, if necessary
      }
}
        File GreetingThread.java
01: import java.util.Date;
02:
03: /**
04: A thread that repeatedly prints a greeting.
05: */
06: public class GreetingThread extends Thread
07: {
08: /**
09:     Constructs the thread object.
10:     @param aGreeting the greating to display
11: */
12: public GreetingThread(String aGreeting)
13: {
14:     greeting = aGreeting;
15: }
16:
17: public void run()
18: {
19:   try
20:   {
21:     for (int i = 1; i <= REPETITIONS; i++)
22:     {
23:       Date now = new Date();
24:       System.out.println(now + " " + greeting);
25:       sleep(DELAY);
26:     }
27:   }
28:   catch (InterruptedException exception)
29:   {
30:   }
31: }
32:
33: private String greeting;
34:
35: private static final int REPETITIONS = 10;
36: private static final int DELAY = 1000;
37: }
         To Start the Thread
• Construct an object of your thread class
      GreetingThread t = new
  GreetingThread("Hello World");


• Call the start method
      t.start();
   File GreetingThreadTest.java
01: import java.util.Date;
02:
03: /**
04: This program tests the greeting thread by running two
05: threads in parallel.
06: */
07: public class GreetingThreadTest
08: {
09: public static void main(String[] args)
10: {
11:     GreetingThread t1 = new GreetingThread("Hello, World!");
12:     GreetingThread t2 = new GreetingThread("Goodbye, World!");
13:
14:     t1.start();
15:     t2.start();
16: }
17: }
           Thread Scheduler
• The thread scheduler runs each thread for
  a short amount of time called a time slice
• Then the scheduler picks another thread
  from those that are runnable
• A thread is runnable if it is not asleep or
  blocked in some way
• There is no guarantee about the order in
  which threads are executed
       Terminating Threads
• A thread terminates when its run method
  returns

• Do not terminate a thread using the
  deprecated stop method

• Instead, notify a thread that it should
  terminate
    t.interrupt();
           Terminating Threads
• A thread's run method should check occasionally
  whether it has been interrupted
  o Use the isInterrupted method
  o An interrupted thread should release resources,
     clean up, and exit
• The sleep method throws an InterruptedException
  when a sleeping thread is interrupted
  o Catch the exception
  o Terminate the thread
      Terminating a Thread
public void run(
{
  try
  {
         for (int = 1; i <= REPETITIONS &&
  !isInterrupted(); i++)
         {
               //do the work
         }
       }
       catch (InterruptedException exception)
  {
  }
  //cleanup
}
      Corrupting Data with
     Unsynchronized Threads

• When threads share a common object,
  they can conflict with each other.

• In this example, a DepositThread and a
  WithdrawThread both manipulate a single
 BankAccount
       run   Method of DepositThread
public void run()
{
    try
    {
       for (int i = 1; i <= REPETITIONS &&
   !isInterrupted(); i++)
       {
          account.deposit(amount);
          sleep(DELAY);
       }
     }
     catch (InterruptedException exception)
     {
     }
 }
           Sample Application
• Create a BankAccount object

• Create a DepositThread t0 to deposit $100 into
  the account for 10 iterations

• Create a WithdrawThread t1 to withdraw $100
  from the account for 10 iterations

• The result should be zero, but sometimes it
  is not
   Scenario to Explain Non-zero
               Result
• The first thread t0 executes the lines
       System.out.print("Depositing " + amount);
       double newBalance = balance + amount;

• t0 reaches the end of its time slice and t1 gains
  control
• t1 calls the withdraw method which withdraws
  $100 from the balance variable.
• Balance is now -100
• t1 goes to sleep
        Scenario to Explain Non-zero
                    Result
• t0   regains control and picks up where it left off.

• t0   executes the lines
 System.out.println(", new balance is " + newBalance);

 balance = newBalance;


• The balance is now 100 instead of 0 because the
  deposit method used the OLD balance

• This is called a race condition.
             Race condition
• Occurs if the effect of multiple threads on
  shared data depends on the order in which
  the threads are scheduled
• It is possible for a thread to reach the end
  of its time slice in the middle of a
  statement.
• It may evaluate the right-hand side of an
  equation but not be able to store the result
  until its next turn.
Corrupting the Contents of the balance Field
 File BankAccountThreadTest.java
01: import java.util.Random;
02:
03: /**
04: This program runs two threads that deposit and withdraw
05: money from the same bank account.
06: */
07: public class BankAccountThreadTest
08: {
09: public static void main(String[] args)
10: {
11:     BankAccount account = new BankAccount();
12:
13:     DepositThread t0 = new DepositThread(account, 100);
14:     WithdrawThread t1 = new WithdrawThread(account, 100);
15:
16:     t0.start();
17:     t1.start();
18: }
19: }
20:
              File DepositThread.java
01: /**
02: A deposit thread makes periodic deposits to a bank account.
03: */
04: class DepositThread extends Thread
05: {
06: /**
07:     Constructs a deposit thread.
08:     @param anAccount the account into which to deposit money
09:     @anAmount the amount to deposit in each repetition
10: */
11: public DepositThread(BankAccount anAccount, double anAmount)
12: {
13:     account = anAccount;
14:     amount = anAmount;
15: }
16:
17: public void run()
18: {
19:   try
20:   {
21:     for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++)
22:     {
23:       account.deposit(amount);
24:       sleep(DELAY);
25:     }
26:   }
27:   catch (InterruptedException exception)
28:   {
29:   }
30: }
31:
32: private BankAccount account;
33: private double amount;
34:
35: private static final int REPETITIONS = 10;
36: private static final int DELAY = 10;
37: }
             File WithdrawThread.java
01: /**
02: A withdraw thread makes periodic withdrawals from a bank account.
03: */
04: class WithdrawThread extends Thread
05: {
06: /**
07:     Constructs a withdraw thread.
08:     @param anAccount the account from which to withdraw money
09:     @anAmount the amount to withdraw in each repetition
10: */
11: public WithdrawThread(BankAccount anAccount, double anAmount)
12: {
13:     account = anAccount;
14:     amount = anAmount;
15: }
16:
17: public void run()
18: {
19:   try
20:   {
21:     for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++)
22:     {
23:       account.withdraw(amount);
24:       sleep(DELAY);
25:     }
26:   }
27:   catch (InterruptedException exception)
28:   {
29:   }
30: }
31:
32: private BankAccount account;
33: private double amount;
34:
35: private static final int REPETITIONS = 10;
36: private static final int DELAY = 10;
37: }
                File BankAccount.java
01: /**
02: A bank account has a balance that can be changed by
03: deposits and withdrawals.
04: */
05: public class BankAccount
06: {
07: /**
08:     Constructs a bank account with a zero balance
09: */
10: public BankAccount()
11: {
12:     balance = 0;
13: }
14:
15: /**
16:     Deposits money into the bank account.
17:     @param amount the amount to deposit
18:   */
19:   public void deposit(double amount)
20:   {
21:     System.out.print("Depositing " + amount);
22:     double newBalance = balance + amount;
23:     System.out.println(", new balance is " + newBalance);
24:     balance = newBalance;
25:   }
26:
27:   /**
28:     Withdraws money from the bank account.
29:     @param amount the amount to withdraw
30:   */
31:   public void withdraw(double amount)
32:   {
33:     System.out.print("Withdrawing " + amount);
34:     double newBalance = balance - amount;
35:     System.out.println(", new balance is " + newBalance);
36:     balance = newBalance;
37:   }
38:
39: /**
40:   Gets the current balance of the bank account.
41:   @return the current balance
42: */
43: public double getBalance()
44: {
45:   return balance;
46: }
47:
48: private double balance;
49: }
     Solving the Race Condition
              Problem
• A thread must be able to lock an object
  temporarily
• When a thread has the object locked, no
  other thread can modify the state of the
  object.
• In Java, use synchronized methods to do this
• Tag all methods that contain thread-sensitive
  code with the keyword synchronized
        Synchronized Methods
public class BankAccount
{
   public synchronized void deposit(double amount)
   {
      . . .
   }

    public synchronized void withdraw(double amount)
    {
       . . .
    }
    . . .
}
         Synchronized Methods
• By declaring both the deposit and withdraw
  methods to be synchronized
  o Our program will run correctly
  o Only one thread at a time can execute either
    method on a given object
  o When a thread starts one of the methods, it is
    guaranteed to execute the method to completion
    before another thread can execute a
    synchronized method on the same object.
        Synchronized Methods
• By executing a synchronized method:

  o The thread acquires the object lock.
  o No other thread can acquire the lock.
  o No other thread can modify the state of the
    object until the first thread is finished
       Visualization of Synchronized
             Thread Behavior
• Imagine the object is a restroom that only one person can
  use at a time
• The threads are people
• If the restroom is empty, a person may enter
• If a second person finds the restroom locked, the second
  person must wait until it is empty
• If multiple people want to gain access to the restroom ,
  they all wait outside
• The people may not form an orderly queue;
• A randomly chosen person may gain access when the
  restroom becomes available again
                   Deadlock
• A deadlock occurs if no thread can proceed because
  each thread is waiting for another to do some work
  first

• BankAccount example
  public synchronized void withdraw(double amount)
  {
     while (balance < amount)
        //wait for balance to grow
     . . .
  }
                      Deadlock
• The method can lead to deadlock
• The thread sleeps to wait for balance to grow, but it
  still has the lock
• No other thread can execute the synchronized
  deposit method
• If a thread tries to call deposit, it is blocked until the
  withdraw method exits
• withdraw method can't exit until it has funds
  available
• DEADLOCK
        Avoiding Deadlock
• The wait method temporarily releases the
  object lock and deactivates the thread

• Restroom analogy
  o Don't want the person in the restroom to go
    to sleep if there is no toilet paper.
  o Think of the person giving up and leaving
  o This gives another person a chance to enter
    and refill the toilet paper
withdraw   Method to Avoid Deadlock

  public synchronized void
    withdraw(double amount)
     throws InterruptedException
  {
     while (balance < amount)
        wait();
  }
              Wait   and NotifyAll
• A thread that calls wait is in a blocked state
• It will not be activated by the thread scheduler
  until it is unblocked
• It is unblocked when another thread calls
  notifyAll


• When a thread calls notifyAll, all threads
  waiting on the object are unblocked
• Only the thread that has the lock can call
  notifyAll
   Restroom wait/notifyAll Analogy
• The thread calling wait corresponds to the
  person who enters the restroom and finds there
  is no toilet paper
• The person then leaves the restroom and waits
  outside
• Other people may enter and leave, but the first
  person just waits
• Eventually an attendant enters the restroom,
  refills the toilet paper, and shouts a notification
• All the waiting people compete for the restroom
  File BankAccountThreadTest.java
              Using synchronized methods
01: import java.util.Random;
02:
03: /**
04: This program runs four threads that deposit and withdraw
05: money from the same bank account.
06: */
07: public class BankAccountThreadTest
08: {
09: public static void main(String[] args)
10: {
11:   BankAccount account = new BankAccount();
12:
13:   DepositThread t0 = new DepositThread(account, 100);
14:   WithdrawThread t1 = new WithdrawThread(account, 100);
15:   DepositThread t2 = new DepositThread(account, 100);
16:   WithdrawThread t3 = new WithdrawThread(account, 100);
17:
18:   t0.start();
19:   t1.start();
20:   t2.start();
21:   t3.start();
22: }
23: }
                File BankAccount.java
01: /**
02: A bank account has a balance that can be changed by
03: deposits and withdrawals.
04: */
05: public class BankAccount
06: {
07: /**
08:     Constructs a bank account with a zero balance
09: */
10: public BankAccount()
11: {
12:     balance = 0;
13: }
14:
15: /**
16:     Deposits money into the bank account.
17:     @param amount the amount to deposit
18:   */
19:   public synchronized void deposit(double amount)
20:   {
21:     System.out.print("Depositing " + amount);
22:     double newBalance = balance + amount;
23:     System.out.println(", new balance is " + newBalance);
24:     balance = newBalance;
25:     notifyAll();
26:   }
27:
28:   /**
29:     Withdraws money from the bank account.
30:     @param amount the amount to withdraw
31:   */
32:   public synchronized void withdraw(double amount)
33:     throws InterruptedException
34:   {
35:     while (balance < amount)
36:       wait();
37:     System.out.print("Withdrawing " + amount);
38:   double newBalance = balance - amount;
39:   System.out.println(", new balance is " + newBalance);
40:   balance = newBalance;
41: }
42:
43: /**
44:   Gets the current balance of the bank account.
45:   @return the current balance
46: */
47: public double getBalance()
48: {
49:   return balance;
50: }
51:
52: private double balance;
53: }
               Animation
• Animation shows different objects moving
  or changing as time progresses

• Thread programming is useful in animation

• An algorithm animation helps visualize the
  steps in the algorithm
        Algorithm Animation
• Runs in a separate thread that periodically
  updates an image of the current state of the
  algorithm
• It then pauses so the user can see the
  change
• After a short time the algorithm thread
  wakes up and runs to the next point of
  interest
• It updates the image again and pauses again
         Selection Sort Algorithm
                Animation
• Items in the algorithm's state
   o The array of values
   o The size of the already sorted area
   o The currently marked element

• To visualize the algorithm
  o Show the sorted part of the array in a different
    color
  o Mark the currently visited array element in red.
           Selection Sort Algorithm
                  Animation
• Add an Applet instance variable to the algorithm
  class

    public class SelectionSorter
    {
      public SelectionSorter(int[] anArray, Applet anApplet)
      {
         a = anArray;
         applet = anApplet;
      }
      . . .
      private Applet applet
}
         Selection Sort Algorithm
                Animation
• Supply a pause method that sleeps for a time
  proportional to the number of steps involved,
  one unit of time for each array element visited

  public void pause(int steps)
      throws InterruptedException
  {
      if (Thread.currentThread().isInterrupted())
           throw new InterruptedException();
      applet.repaint();
      Thread.sleep(steps * DELAY);
  }
          Selection Sort Algorithm
                 Animation
• Add a draw method to draw the current state of the
  array
  public void draw(Graphics2D g2)
  {
     int deltaX = applet.getWidth() / a.length;
     for (int i = 0; i < a.length; i++)
     {
        if (i == markedPosition)
           g2.setColor(Color.red);
        else if (i <= alreadySorted)
           g2.setColor(Color.blue);
        else
           g2.setColor(Color.black);
        g2.draw(new Line2D.Double(i * deltaX, 0,
           i * deltaX, a[i]));
     }
  }
          Selection Sort Algorithm
                 Animation
• Add a pause to the minimumPosition method
public int minimumPosition(int from)
   throws InterruptedException
{
   int minPos = from;
   for (int i = from + 1; i < a.length; i++)
   {
       if (a[i] < a[minPos]) minPos = i;
       markedPosition = i;
       pause(2);
   }
  return minPos;
}

• Add a similar pause to the sort method
   Applet to Provide User Interface
• Start the animation with a mousePressed event
  If an animation is already running, interrupt the
  thread to terminate it
public class SelectionSortApplet extends Applet
{
   public SelectionSortApplet()
   {
      class MousePressListener extends MouseAdapter
      {
         public void mousePressed(MouseEvent event)
         {
             if (animation != null &&
  animation.isAlive())
               animation.interrupt();
            startAnimation();
         }
       }

       MouseListener listener = new MousePressListener();
       addMouseListener(listener);
       . . .
       animation = null;
     }
    . . .
    private Thread Animation
}
  Applet to Provide User Interface
• The Applet's paint method calls the draw
  method of the algorithm

  public void paint(Graphics g)
  {
     if (sorter == null) return;
     Graphics2D g2 = (Graphics2D)g;
     sorter.draw(g2);
  }
  Applet to Provide User Interface
• The Applet provides a startAnimation method

  o It constructs a SelectionSorter with a new
    array and a this reference to the Applet

  o It constructs a thread

  o The thread's run method calls the sorter's
   sort method
  Applet to Provide User Interface
• startAnimation    method
• public void startAnimation()
{
   class AnimationThread extends Thread
   {
      public void run()
      {
         try
         {
             sorter.sort();
         }
         catch (InterruptedException exception)
         {
             }
         }
     }

     int[] values = ArrayUtil.randomIntArray(30,
    300);
     sorter = new SelectionSorter(values, this);
     animation = new AnimationThread();<
     animation.start();
}
A Step in the Animation of the
  Selection Sort Algorithm
   File SelectionSortApplet.java
01: import java.applet.Applet;
02: import java.awt.Color;
03: import java.awt.Graphics;
04: import java.awt.Graphics2D;
05: import java.awt.event.MouseEvent;
06: import java.awt.event.MouseAdapter;
07: import java.awt.event.MouseListener;
08:
09: /**
10: This applet animates the selection sort algorithm.
11: */
12: public class SelectionSortApplet extends Applet
13: {
14: /**
15:     Constructs the applet and sets up the mouse handler.
16:     Click on the surface of the applet to start the animation.
17: */
18: public SelectionSortApplet()
19: {
20:   class MousePressListener extends MouseAdapter
21:   {
22:     public void mousePressed(MouseEvent event)
23:     {
24:       if (animation != null && animation.isAlive())
25:          animation.interrupt();
26:       startAnimation();
27:     }
28:   }
29:
30:   MouseListener listener = new MousePressListener();
31:   addMouseListener(listener);
32:   setBackground(Color.lightGray);
33:
34:   sorter = null;
35:   animation = null;
36: }
37:
38:   public void paint(Graphics g)
39:   {
40:     if (sorter == null) return;
41:     Graphics2D g2 = (Graphics2D)g;
42:     sorter.draw(g2);
43:   }
44:
45:   /**
46:     Starts a new animation thread.
47:   */
48:   public void startAnimation()
49:   {
50:     class AnimationThread extends Thread
51:     {
52:       public void run()
53:       {
54:         try
55:         {
56:           sorter.sort();
57:         }
58:       catch (InterruptedException exception)
59:       {
60:       }
61:     }
62:   }
63:
64:   int[] values = ArrayUtil.randomIntArray(30, 300);
65:   sorter = new SelectionSorter(values, this);
66:   animation = new AnimationThread();
67:   animation.start();
68: }
69:
70: private SelectionSorter sorter;
71: private Thread animation;
72: }
              File SelectionSorter
001: import java.applet.Applet;
002: import java.awt.Color;
003: import java.awt.Graphics2D;
004: import java.awt.geom.Line2D;
005:
006: /**
007: This class sorts an array, using the selection sort
008: algorithm
009: */
010: public class SelectionSorter
011: {
012: /**
013:     Constructs a selection sorter.
014:     @param anArray the array to sort.
015: */
016: public SelectionSorter(int[] anArray, Applet anApplet)
017: {
018:       a = anArray;
019:       applet = anApplet;
020:   }
021:
022:   /**
023:     Sorts the array managed by this selection sorter.
024:   */
025:   public void sort()
026:     throws InterruptedException
027:   {
028:     for (int i = 0; i < a.length - 1; i++)
029:     {
030:       int minPos = minimumPosition(i);
031:       swap(minPos, i);
032:       // for animation
033:       alreadySorted = i;
034:       pause(2);
035:     }
036:   }
037:
038:   /**
039:     Finds the smallest element in a tail range of the array
040:     @param from the first position in a to compare
041:     @return the position of the smallest element in the
042:     range a[from]...a[a.length - 1]
043:   */
044:   private int minimumPosition(int from)
045:     throws InterruptedException
046:   {
047:     int minPos = from;
048:     for (int i = from + 1; i < a.length; i++)
049:     {
050:       if (a[i] < a[minPos]) minPos = i;
051:       // for animation
052:       markedPosition = i;
053:       pause(2);
054:     }
055:     return minPos;
056:   }
057:
058:   /**
059:     Swaps two entries of the array.
060:     @param i the first position to swap
061:     @param j the second position to swap
062:   */
063:   private void swap(int i, int j)
064:   {
065:     int temp = a[i];
066:     a[i] = a[j];
067:     a[j] = temp;
068:   }
069:
070:   /**
071:     Draws the current state of the sorting algorithm.
072:     @param g2 the graphics context
073:   */
074:   public void draw(Graphics2D g2)
075:   {
076:     int deltaX = applet.getWidth() / a.length;
077:     for (int i = 0; i < a.length; i++)
078:       {
079:           if (i == markedPosition)
080:              g2.setColor(Color.red);
081:           else if (i <= alreadySorted)
082:              g2.setColor(Color.blue);
083:           else
084:              g2.setColor(Color.black);
085:           g2.draw(new Line2D.Double(i * deltaX, 0,
086:              i * deltaX, a[i]));
087:       }
088:   }
089:
090:   /**
091:     Pauses the animation.
092:     @param steps the number of steps to pause
093:   */
094:   public void pause(int steps)
095:     throws InterruptedException
096:   {
097:     if (Thread.currentThread().isInterrupted())
098:      throw new InterruptedException();
099:    applet.repaint();
100:    Thread.sleep(steps * DELAY);
101: }
102:
103: private int[] a;
104:
105: // the applet is needed for pausing the animation
106: private Applet applet;
107:
108: // these fields are needed for drawing
109: private int markedPosition = -1;
110: private int alreadySorted = -1;
111:
112: private static final int DELAY = 100;
113: }

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:7
posted:8/1/2011
language:English
pages:72