Multithreading Horstmann ch.9 Multithreading Threads Thread - - PDF document

multithreading
SMART_READER_LITE
LIVE PREVIEW

Multithreading Horstmann ch.9 Multithreading Threads Thread - - PDF document

Multithreading Horstmann ch.9 Multithreading Threads Thread states Thread interruption Race condition Lock Built-in lock java.util.concurrent library Animation example Single vs. Multiple Threads Finish


slide-1
SLIDE 1

Multithreading

Horstmann ch.9

slide-2
SLIDE 2

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-3
SLIDE 3

Single vs. Multiple Threads

  • Finish each line of

bullets before starting new line

  • Allow simultaneous

drawing of several lines

ThreadTester1 ThreadTester2

slide-4
SLIDE 4

Single vs. Multiple Threads

Using single thread:

in method actionPerformed: ... for (int i=0; i<10; i++) { ”draw single bullet”; Thread.sleep(500); } ...

slide-5
SLIDE 5

Running Threads

public class MyRunnable implements Runnable { public void run() { thread action } } ... Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start();

Specify action Construct thread from Runnable object Start thread

slide-6
SLIDE 6

Single vs. Multiple Threads

Using single thread:

in method actionPerformed: ... for (int i=0; i<10; i++) { ”draw single bullet”; Thread.sleep(500); } ...

Using multiple threads: In method actionPerformed: Runnable r = new Runnable() { public void run() { } } Thread t = new Thread(r); t.start();

slide-7
SLIDE 7

QUIZ

public static void main(String[] args) { Runnable r1 = new Producer(); Runnable r2 = new Producer(); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } How many threads?

  • 1. One
  • 2. Two
  • 3. Three
  • 4. None
  • 5. I don’t know

Multiple threads

slide-8
SLIDE 8

Starting Two Threads

public static void main(String[] args) { Runnable r1 = new Producer(); Runnable r2 = new Producer(); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); }

slide-9
SLIDE 9

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-10
SLIDE 10

Thread states

  • Each thread has

– State (new, runnable, blocked, dead), and – priority

Thread blocked when

  • Sleeping
  • Waiting for I/O
  • Waiting to acquire lock
  • Waiting for condition

Scheduler activates the runnable thread of max priority if

  • a thread has completed its time

slice

  • a thread has blocked itself
  • a thread with higher priority has

become runnable

slide-11
SLIDE 11

Thread scheduling

public static void main(String[] args) { Runnable r1 = new Producer(“goddag”); Runnable r2 = new Producer(“farvel”); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); }

Output depends

  • n scheduler:

“goddag” “goddag” “farvel” “farvel” “farvel” “goddag” “farvel” …

public class Producer implements Runnable { public Producer(String a) { greeting = a; } public void run() { try { for (int i = 1; i <= 10; i++) { System.out.println(i + ": " + greeting); Thread.sleep(100); } } catch (InterruptedException e) {} } private String greeting; }

slide-12
SLIDE 12

QUIZ

Thread T1 based on run method public void run { try { Thread.sleep(100000); } catch (InterruptedException e) {} } Thread T2 based on run method public void run { factor(785678564567385635789) } Which thread(s) are runnable throughout there ”lives” from start to termination?

  • 1. T1
  • 2. T2
  • 3. None
  • 4. Both
  • 5. I don’t know

Thread scheduling Integer factor method from ”noter” ch. 1 (it is slow)

slide-13
SLIDE 13

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-14
SLIDE 14

Thread interaction

  • Recursive Fibonacci

– May take long time – Window freezes

  • Compute in separate threads

– Old slow thread may overwrite result from new fast thread? – Interrupt old threads!

ThreadTester3

slide-15
SLIDE 15

Terminating Threads

  • Thread terminates when run exits
  • Or ask thread to finish by calling interrupt
  • Thread may check for interrupt by calling

Thread.currentThread().isInterrupted()

  • sleep, wait throw InterruptedException

when thread is interrupted

slide-16
SLIDE 16

private Thread t = null; public void actionPerformed(ActionEvent e) { if (t!=null) t.interrupt(); Runnable r = new Runnable() { public void run() { try { long res = fib(Integer.parseInt(input.getText())); if (!Thread.currentThread().isInterrupted()) recResult.setText(res+""); } catch (InterruptedException e) {} } }; t = new Thread(r); t.start(); } private long fib(int n) throws InterruptedException { if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); if (n <= 1) return 1; else return fib(n - 1) + fib(n - 2); } Code of anonymous class implementing ActionListener

slide-17
SLIDE 17

QUIZ

public class Test1 implements Runnable { public void run() { try { for (int i=1; i<=10; i++) { System.out.println(i); Thread.sleep(1000); } } catch (InterruptedException e) { } } } The catch statement is empty?

  • 1. Compiler error
  • 2. Legal code, but better style to omit try-catch
  • 3. Legal code, try-catch is necessary, but empty catch is bad style
  • 4. Legal code, try-catch is necessary, empty catch is good style
  • 5. I don’t know

Thread termination

slide-18
SLIDE 18

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-19
SLIDE 19

Shared Resource

Producer Thread ”goddag” Producer Thread ”farvel” Consumer Thread Queue

  • bject

Bounded Queue: max 10 elements

slide-20
SLIDE 20

Producer Thread

int i = 1; while (i <= 100) { if (!queue.isFull()) { queue.add(i + ": " + greeting); i++; } Thread.sleep((int)(Math.random() * DELAY)); } Producer Thread ”goddag” Producer Thread ”farvel” Consumer Thread Queue

  • bject

Bounded Queue: max 10 elements

slide-21
SLIDE 21

Consumer Thread

int i = 1; while (i <= 200) { if (!queue.isEmpty()) { Object greeting = queue.remove(); System.out.println(greeting); i++; } Thread.sleep((int)(Math.random() * DELAY)); } Producer Thread ”goddag” Producer Thread ”farvel” Consumer Thread Queue

  • bject

Bounded Queue: max 10 elements

slide-22
SLIDE 22
  • Expected Program

Output

1: goddag 1: farvel 2: goddag 3: goddag ... 99: farvel 100: farvel

  • Possible output

... 10: goddag 11: farvel ... 15: goddag 11: farvel ...

  • Why?
slide-23
SLIDE 23

Queue: Circular Array Implementation

public void add(E newValue) { elements[tail] = newValue; tail++; size++; if (tail == elements.length) { tail = 0; } } <junk> <junk> <junk> 4 3 2 1 <junk>

Head: Tail:

3 2 1 <junk> <junk> <junk> <junk> 4

Tail: Head:

slide-24
SLIDE 24

Race Condition

  • First thread calls add and executes

elements[tail] = newValue; First thread at end of time slice

  • Second thread calls add and executes

elements[tail] = newValue; tail++; Second thread at end of time slice

  • First thread executes

tail++;

slide-25
SLIDE 25

QUIZ

Producer Thread:

BoundedQueue<String> queue = new BoundedQueue<String>(10); for (int i = 1; i <= 100; i++) { queue.add(i + ": " + greeting); Thread.sleep((int)(Math.random() * DELAY)); }

Consumer Thread:

BoundedQueue<String> queue = new BoundedQueue<String>(10); for (int i = 1; i <= 100; i++) { Object greeting = queue.remove(); System.out.println(greeting); Thread.sleep((int)(Math.random() * DELAY)); } Race condition Could race condition occur when running these thread in parallel?

  • 1. Yes
  • 2. No
  • 3. I don’t know
slide-26
SLIDE 26

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-27
SLIDE 27

Locks

  • Thread can acquire lock
  • When another thread tries to acquire same lock,

it blocks

  • When first thread releases lock, other thread is

unblocked and tries again

  • Two kinds of locks

– Objects of class implementing java.util.concurrent.Lock interface type, usually ReentrantLock – Locks that are built into every Java object

slide-28
SLIDE 28

private Lock aLock = new ReentrantLock(); . . . public void add(E newValue) { aLock.lock(); try { elements[tail] = newValue; tail++; size++; if (tail==elements.length) tail = 0; } finally { aLock.unlock(); } } Consumer or producer thread executing lock() has exclusive access to add/remove methods – even when time slice is up – until unlock() public E remove() { aLock.lock(); try { E r = (E) elements[head]; head++; size--; if (head==elements.length) head = 0; return r; } finally { aLock.unlock(); } }

slide-29
SLIDE 29

Producer Thread

int i = 1; while (i <= 100) { if (!queue.isFull()) { queue.add(i + ": " + greeting); i++; } Thread.sleep((int)(Math.random() * DELAY)); }

Good: add is protected by lock Bad: Another producer thread may fill up the queue between isFull() check and add() Solution: Must move isFull() check inside protected add()

slide-30
SLIDE 30

QUIZ

public void add(E newValue) throws InterruptedException { aLock.lock(); try { while( isFull() ) { Thread.sleep(1000); } ... } finally {aLock.unlock();} }

Dead lock Does it work to put isfull() check inside lock protected add()?

  • 1. No, race condition may still occur
  • 2. Yes, race condition cannot occur, and this code works fine
  • 3. No, race condition cannot occur – but a new problem arises…
  • 4. I don’t know
slide-31
SLIDE 31

Using condition object to avoid deadlock

private Lock aLock = new ReentrantLock(); private Condition spaceAvailableCondition = aLock.newCondition(); public void add(E newValue) throws InterruptedException { aLock.lock(); try { while (isFull()) spaceAvailableCondition.await(); . . . } finally {aLock.unlock();} } public E remove() throws InterruptedException { aLock.lock(); try { . . . spaceAvailableCondition.signalAll(); return r; } finally {aLock.unlock();} } Calling await blocks the thread and releases the lock Calling signalAll() unblocks all threads awaiting this condition (they remain blocked until getting the lock)

slide-32
SLIDE 32

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-33
SLIDE 33

Object Locks

  • Each object has a lock
  • Calling a synchronized method acquires lock of implicit parameter
  • Leaving the synchronized method releases lock
  • Easier than explicit Lock objects

public class BoundedQueue<E> { public synchronized void add(E newValue) { ... } public synchronized E remove() { ... } ... }

slide-34
SLIDE 34

Object Locks

  • Each implicit lock has one associated (anonymous)

condition object

  • wait() blocks current thread and adds it to wait set
  • notifyAll() unblocks waiting threads

public synchronized void add(E newValue) throws InterruptedException { while (isFull()) wait(); elements[tail] = anObject; . . . notifyAll(); }

Just one condition object Used by both threads waiting due to full queue and due to empty queue

slide-35
SLIDE 35

QUIZ

Thread blocking What is not reason for blocking a thread?

  • 1. Sleeping
  • 2. Waiting for I/O
  • 3. Time slice is up
  • 4. Waiting to acquire lock
  • 5. Waiting for a condition
  • 6. I don’t know
slide-36
SLIDE 36

QUIZ

When is InterruptedException thrown?

  • 1. when Thread.sleep(..) returns
  • 2. when <condition>.await() returns
  • 3. when other thread calls this threads interrupt method
  • 4. when other thread calls this threads interrupt method

while this thread is blocked

  • 5. I don’t know

Thread interruption

slide-37
SLIDE 37

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-38
SLIDE 38

Use java.util.concurrent library

Main thread:

BlockingQueue<String> queue = new LinkedBlockingQueue<String>(10);

Producer Thread:

for (int i = 1; i <= 100; i++) { queue.put(i + ": " + greeting); Thread.sleep((int)(Math.random() * DELAY)); }

Consumer Thread:

for (int i = 1; i <= 100; i++) { Object greeting = queue.take(); System.out.println(greeting); Thread.sleep((int)(Math.random() * DELAY)); } Synchronized queue with space for 10 elements Producer thread is made to wait until queue has available space Consumer thread is made to wait until queue is nonempty

slide-39
SLIDE 39

Multithreading

  • Threads
  • Thread states
  • Thread interruption
  • Race condition
  • Lock
  • Built-in lock
  • java.util.concurrent library
  • Animation example
slide-40
SLIDE 40

Algorithm Animation

  • Use thread to make progress in algorithm
  • Display algorithm state
  • Example: Animate MergeSorter (similar to java.util.Arrays.sort)
  • Pause inside compare method
  • Pass custom comparator

Comparator<Double> comp = new Comparator<Double>() { public int compare(Double d1, Double d2) { draw current state pause thread return d1.compareTo(d2); } };

slide-41
SLIDE 41

Algorithm Animation

slide-42
SLIDE 42

public class Sorter implements Runnable { public Sorter(Double[] values, ArrayComponent panel) { this.values = values; this.panel = panel; } public void run() { Comparator<Double> comp = new Comparator<Double>() { public int compare(Double d1, Double d2) { panel.setValues(values, d1, d2); try { Thread.sleep(DELAY); } catch (InterruptedException exception) { Thread.currentThread().interrupt(); } return d1.compareTo(d2); }; MergeSorter.sort(values, comp); panel.setValues(values, null, null); } private Double[] values; private ArrayComponent panel; private static final int DELAY = 100; } array being sorted

slide-43
SLIDE 43

Pausing and Running the Animation

  • Want to pause animation until "Run" or "Step"

button is clicked

  • Need to coordinate UI thread, animation thread
  • Try to use built-in thread-safe construct in

java.util.concurrent

  • Trick: Use a blocking queue
  • Button click adds string "Run" or "Step" to queue
  • Animation thread calls take on the queue, blocks

if no string inserted BlockingQueue<String> queue;

slide-44
SLIDE 44

User Interface Thread

stepButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { queue.add("Step"); runButton.setEnabled(true); } }); runButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { runButton.setEnabled(false); queue.add("Run"); } });

slide-45
SLIDE 45

Animation Thread

public int compare(Double d1, Double d2) { try { String command = queue.take(); if (command.equals("Run")) { Thread.sleep(DELAY); if (!"Step".equals(queue.peek())) queue.add("Run"); } } catch (InterruptedException exception) { Thread.currentThread().interrupt(); } panel.setValues(values, d1, d2); return d1.compareTo(d2); } ... private BlockingQueue<String> queue;

slide-46
SLIDE 46