Multithreading - brics

lightnewsΛογισμικό & κατασκευή λογ/κού

18 Νοε 2013 (πριν από 3 χρόνια και 8 μήνες)

70 εμφανίσεις

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 each line of
bullets before
starting new line
•Allow simultaneous
drawing of several
lines
ThreadTester1
ThreadTester2
Single vs. Multiple
Threads
Using singlethread:
in method actionPerformed:
...
for (int i=0; i<10; i++) {
”draw single bullet”;
Thread.sleep(500);
}
...
Running Threads
public class MyRunnable implements Runnable {
public void run() {
thread action
}
}
...
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
Specifyaction
Constructthreadfrom Runnableobject
Start thread
Single vs. Multiple
Threads
Using singlethread:
in method actionPerformed:
...
for (int i=0; i<10; i++) {
”draw single bullet”;
Thread.sleep(500);
}
...
Using multiplethreads:
In method actionPerformed:
Runnable r = new Runnable() {
public void run() {
}
}
Thread t = new Thread(r);
t.start();
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 manythreads?
1.One
2.Two
3.Three
4.None
5.I don’tknow
Multiple threads
Starting Two Threads
public static void main(String[] args) {
Runnabler1 = new Producer();
Runnabler2 = new Producer();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
Multithreading
•Threads •Thread states
•Thread interruption
•Race condition
•Lock
•Built-in lock
•java.util.concurrent library
•Animation example
Thread states
•Each thread has
–State (new, runnable, blocked, dead), and
–priority
Threadblockedwhen
•Sleeping
•Waitingfor I/O
•Waitingto acquirelock
•Waitingfor 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
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
on 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;
}
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)
}
factor methodfrom ”noter” ch. 1
Whichthread(s) arerunnable
throughoutthere”lives” from
start to termination?
1.T1
2.T2
3.None
4.Both
5.I don’tknow
Thread scheduling
Multithreading
•Threads
•Thread states •Thread interruption
•Race condition
•Lock
•Built-in lock
•java.util.concurrent library
•Animation example
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
Terminating Threads
•Thread terminates when runexits
•Or ask thread to finish by calling
interrupt
•Thread may check for interrupt by call
Thread.currentThread().isInterr
upted()
•sleep, waitthrow
InterruptedExceptionwhen thread
interrupted
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);
}
Codeof anonymousclassimplementingActionListener
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 catchstatement is empty?
1.Compiler error
2.Legal code, but betterstyleto omittry-catch
3.Legal code, try-catchis necessary, but emptycatchis bad style
4.Legal code, try-catchis necessary, emptycatchis goodstyle
5.I don’tknow
Thread termination
Multithreading
•Threads
•Thread states
•Thread interruption •Race condition
•Lock
•Built-in lock
•java.util.concurrent library
•Animation example
Shared Resource
Producer
Thread
”goddag”
Producer
Thread”farvel”
Consumer
Thread
Queue
object
BoundedQueue:
max 10 elements
Producer Thread
int i = 1;
while (i <= 100) {
if (!queue.isFull()) {
queue.add(i + ": " + greeting);
i++;
}
Thread.sleep((int)(Math.random() * DELAY));
}
Consumer Thread
int i = 1;
while (i <= 100) {
if (!queue.isEmpty()) {
Object greeting = queue.remove();
System.out.println(greeting);
i++;
}
Thread.sleep((int)(Math.random() * DELAY));
}
•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?
Queue:
Circular Array Implementation
public void add(E newValue) {
elements[tail] = newValue;
tail++;
size++;
if (tail == elements.length) {
tail = 0;
}
}
Race Condition
•First thread calls addand executes
elements[tail] = newValue;
First thread at end of time slice
•Second thread calls addand executes
elements[tail] = newValue;
tail++;
Second thread at end of time slice
•First thread executes
tail++;
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
Couldrace conditionoccurwhen
runningthesethreadin parallel?
1.Yes
2.No
3.I don’tknow
Multithreading
•Threads
•Thread states
•Thread interruption
•Race condition •Lock
•Built-in lock
•java.util.concurrent library
•Animation example
Locks
•Thread can acquirelock
•When another thread tries to acquire same lock,
it blocks
•When first thread releaseslock, 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
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();
}
}
Consumerorproducer threadexecutinglock() has
exclusiveaccessto add/removemethods–evenwhen
time sliceis up –untilunlock()
public E remove() {
aLock.lock();
try{
E r = (E) elements[head];
head++;
size--;
if (head==elements.length)
head = 0;
return r;
} finally{
aLock.unlock();
}
}
Producer Thread
int i = 1;
while (i <= 100) {
if (!queue.isFull()) {
queue.add(i + ": " + greeting);
i++;
}
Thread.sleep((int)(Math.random() * DELAY));
}
Good:addis
protectedby lock
Bad:Anotherproducer thread
mayfillup the queuebetween
isFull()check and add()
Solution:Must moveisFull()check
insideprotectedadd()
QUIZ
public void add(E newValue)
throws InterruptedException {
aLock.lock();
try {
while( isFull() ) {
Thread.sleep(1000);
}
...
} finally {aLock.unlock();}
}
Dead lock
Doesit workto put isfull()check insidelockprotectedadd()?
1.No, race conditionmaystill occur
2.Yes, race conditioncannotoccur, and thiscodeworksfine
3.No, race conditioncannotoccur–but a new problem arises…
4.I don’tknow
Using condition object to avoid deadlock
private Lock aLock = new ReentrantLock();
private ConditionspaceAvailableCondition =
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();}
}
Callingawaitblocksthe
threadand releasesthe lock
CallingsignalAll()
unblocksall threads
awaitingthiscondition
(theyremainblockeduntilgettingthe lock)
Multithreading
•Threads
•Thread states
•Thread interruption
•Race condition
•Lock •Built-in lock
•java.util.concurrent library
•Animation example
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 synchronizedvoid add(E newValue) { ... }
public synchronizedE remove() { ... }
...
}
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 oneconditionobject
Usedby boththreadswaiting
due to fullqueueand due to
emptyqueue
QUIZ
Thread blocking
Whatis
not
reasonfor blockinga 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
QUIZ
Whenis InterruptedExceptionthrown?
1.whenThread.sleep(..) returns
2.when<condition>.await() returns
3.whenotherthreadcallsthisthreadsinterruptmethod
4.whenotherthreadcallsthisthreadsinterruptmethod
whilethisthreadis blocked
5.I don’tknow
Thread interruption
Multithreading
•Threads
•Thread states
•Thread interruption
•Race condition
•Lock
•Built-in lock •java.util.concurrent library
•Animation example
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));
}
Synchronizedqueuewithspace
for 10 elements
Producer threadis made to wait
untilqueuehas availablespace
Consumerthreadis made to wait
untilqueueis nonempty
Multithreading
•Threads
•Thread states
•Thread interruption
•Race condition
•Lock
•Built-in lock
•java.util.concurrent library •Animation example
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);
}
};
Algorithm Animation
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
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 thequeue, blocks
if no string inserted
BlockingQueue<String> queue;
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");
}
});
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;