CS4273: Distributed System Technologies and Programming I

advertisement
CS4273: Distributed System Technologies and Programming I
Lecture 4: Java Threads and Multithread Programming
Multi-threading
Threads
• A thread is a thread of control flow of
executing a piece program, similar to a
process.
• Multi-threading is a technique of concurrent
programming, which runs multiple threads on
one piece of program.
• Threads are running in a pseudo-parallel
fashion.
• Servers and animation programs often use
multiple threads.
Memory
Thread1
PC
Thread2
PC
Thread3
PC
Code Segment
2
States of a Thread Life Cycle
• run queue: priority queue
Head
head = Thread.currentThread();
• wait queue: activated by notify()
Head
Tail
Blocked
Dead
NewBorn
sleep()
• sleep queue:
Head
Tail
start()
notify()
wait()
Tail
Running
Runnable
yield()
3
Methods in Thread Class
run() method
• run() method is the program body of a thread. A thread executes run
method when it starts. You need to override this method to let the
thread do your work!
Methods called by threads:
• sleep(ms): make the caller sleep for N milli-seconds.
• yield(): make the caller non-selfish thread. The caller doesn’t mind to
give out the CPU to other threads (of the same priority).
• wait() : the caller blocks itself until being waken up.
• notify(): wake up a thread in wait-queue (by moving the thread from
wait-queue to run-queue). The caller still holds CPU after the call.
• notifyAll(): wake up all threads in wait-queue.
4
Methods in Thread Class (Cont.)
Methods called by control programs (or threads)
• start(): start the thread. It places the thread to the tail of
run-queue.
• setPriority(Thread.MAX_PRIORITY - 2).
• isAlive(): check if a thread is still executing run method.
• currentThread(): return the current running thread.
5
Example of a thread program
public class mythread extends JApplet implements Runnable {
……….
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start(); }
}
public void stop() {
// N.B. thread.stop method was deprecated!
runner = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
// N.B. if “runner’ is null, it won’t do anything
while (runner == thisThread) {
thisThread.sleep(t);
repaint();
………
}
6
Thread Creation
There are two ways to create threads:
1. extend the Thread class to define your thread-class and
then construct objects out of your thread-class.
2. use the Runnable interface and implement the run
method of the interface.
7
Example of extending Thread class
class BellThread extends Thread{
String Sound;
BellThread (String Sound ) {
this.Sound = Sound;
}
process
Dong
Thread
Ding
Thread
public void run(){
while(true){
System.out.println (Sound + " ");
try{sleep(20); } catch(Exception e){ return; }
}
}
public static void main(String[] args){
new BellThread(“Ding”).start();
new BellThread(“Dong”).start();
}
OS
}
8
Example of Thread Switching
public class threadSwitch extends JApplet {
int threadID = 0, star = 0, hash = 0;
public void init() {
StarThread runner1 = new StarThread();
runner1.start();
HashThread runner2 = new HashThread();
runner2.start();
}
public void paint(Graphics g) {
super.paint(g);
switch(threadID) {
case 1: g.drawString("*", star*10, 50);
break;
case 2: g.drawString("#", hash*10, 100);
}
}
class StarThread extends Thread {
public void run() {
while (true){
threadID = 1;
if (star >= 50 ) star = 0;
else star++;
repaint(); }
}}
class HashThread extends Thread {
public void run() {
while (true){
threadID = 2;
if (hash >= 50 ) hash = 0;
else hash++;
repaint(); }
}}
9
Runnable Interface
•
•
•
In addition to extending Thread class, an application often
needs to extend from another class, e.g., Applet. But Java
doesn’t allow multiple inheritance. Runnable interface is
for this purpose.
Runnable interface has only one method run(). You need
to implement the run method.
Thread class constructor creates threads out of Runnable
objects. Thread has two constructors:
public Thread (Runnable target);
the constructed thread object uses target’s run method!
public Thread(Runnable target, String name);
the save as above, but the new thread object has a name.
10
Example of Threads using Runnable Interface
class BellRunnable implements Runnable {
BellRunnable(String sound){
this.sound = sound;
}
public void run() {
for(int i=1;i<=100;i++){
System.out.println(sound + " ");
try{Thread.sleep(20); }
catch (Exception e){ return;}
}
}
public static void main(String[] args) {
BellRunnable Ding = new BellRunnable(“Ding”);
Thread DingThread = new Thread(Ding);
DingThread.start();
BellRunnable Dong = new BellRunnable(“Dong”);
new Thread(Dong).start();
}
11
Applets Implement Runnable Interface of Threads
•
•
Runnable interface has only one method run, you can implement the Runnable
interface in any class by implementing the run method.
It is most often used together with Applet class.
class ThreadApplet extends JApplet implements Runnable {
private Thread runner;
……
public void start() {
if (runner == null) {
runner = new Thread (this); // run of this class
runner.start (); }
}
public void run() {
// thread-code comes here
……
}
}
12
Thread Control: stop a thread
Methods “stop”, “suspend” and “resume” for thread
control were deprecated due to un-safety.
Stop a thread: add the following codes:
1. set the thread pointer runner to “null” when you
want to stop it:
……
N.B. The following two simple methods
don’t work:
……
2. add the following code at the beginning of run() a) Only set “runner1 = null” without
of the thread:
2nd part, it cannot stop the execution
of runner.
public void run()
Thread thisThread = Thread.currentThread(); b) Simplify the 2nd part as below, it
won’t work either:
while (runner1 == thisThread) {
runner1 = null;
code-of-runner;
}
}
public void run() {
while (runner1!= null) {
code-of-runner;}
}
13
Suspend and Resume a thread
• suspend a thread: use a boolean var to indicate suspending the
thread and the thread blocks itself by “wait()” in run method.
• resume a thread: use “notify()” to resume the thread.
1. use a boolean var.
boolean runnerSuspended;
public synchronized void actionPerformed
(ActionEvent e) {
switch (id) {
case SUSPEND:
runnerSuspended = true; break;
case RESUME:
runnerSuspended = false;
notifyAll();
}
2. use the following code in run().
public void run() {
while (runnerSuspended)
wait();
code-of-runner;}
}
14
Example of using wait/notify for suspend/resume
public class threadControl extends JApplet implements
Runnable, ActionListener {
public void run() {
thisThread = Thread.currentThread();
while (faster == thisThread) {
try { synchronized(this) {
while (fastSuspended)
wait();
Thread.sleep(20);
} catch (InterruptedException e) {}
fast++;
repaint();
}
while (slower == thisThread) {
try { synchronized(this) {
while (slowSuspended)
wait();
Thread.sleep(40);
} catch (InterruptedException e) {}
slow++;
repaint();
}
public synchronized void actionPerformed (Event e) {
if (e.getSource() == fsus)
fastSuspended = true;
else if (e.getSource() == fres) {
fastSuspended = false;
notifyAll();
} else if (e.getSource() == fstp)
faster = null;
………………
15
Concurrent accesses may cause inconsistency
class unsynchBankTest {
public static void main (String [] args) {
Bank b = new Bank ();
for (int i = 1; i <= Ntrans; i++)
new Trans (b).start(); }//concurrent threads
}
class Bank {
Thread1
……
public void transfer ( int from, int to, int amnt) {
……
accounts[from] -= amnt;
load r0, acct[to]
accounts[to] += amnt;
add r0, amnt
}
……
store r0, acct[to]
}
class Transaction extends Thread {
public Trans (Bank b) { bank = b;}
public void run () {
while (true) {
int from = (Bank.Nacct - 1)* Math.random();
// random numbers for to and amnt;
bank.transfer ( from, to, amnt); }
}
Thread2
….
Thread n
Bank
16
synchronized Method for access shared objects
•
•
•
When multiple threads access shared object concurrently,
a monitor is required to guarantee each data access
operation is atomic (non-interruptable).
Java provides a modifier “synchronized” for methods
which requires mutual exclusion. When a method is
declared as synchronized, the monitor ensures that at any
time no more than one thread is active in the monitor (i.e.
accesses the object).
When there is a possibility for two threads to modify a
data object in a method, declare the method (or the codesegment) as synchronized, which makes you free of
mutual exclusion problem.
17
Example of synchronized Methods
class unsynchBankTest {
public static void main (String [] args) {
Bank b = new Bank ();
for (int i = 1; i <= Ntrans; i++)
new Trans (b).start();
}
}
class Bank {
public synchronized void transfer ( int from, to, amnt) {
……
accounts[from] -= amnt; // it’s safe now!
accounts[to] += amnt;
}
……
}
class Trans extends Thread {
public void run () {
while (true) {
int from = (Bank.Nacct - 1)* Math.random();
// random numbers for to and amnt;
bank.transfer ( from, to, amnt);
}
}}
18
Thread Coordination
•
•
•
Threads often need to coordinate with each other to get a job done, such as the
Producer-Consumer problem.
The coordination among threads can be achieved by wait and notify methods.
When a thread cannot proceed further and waits for the change of a state, it
calls wait() to block itself; when a thread changes a state which may unblock
others, it calls notify().
In Java, there is only one wait-queue, a FIFO queue, for each application. If
more than one thread waiting, notify wakes up the head of wait-queue. Threads
cannot wait() on specific events. Therefore, notifyAll() is often used to make
sure the right thread is waken up.
Boy
Monkey
Put
Get
Box
19
Example of Threads Coordination
class Box {
boolean banana = false; //no banana
synchronized void get() {
while (!banana) // ? not use if
wait(); // wait for banana
System.out.println("take banana away”);
banana = false; // no more banana
notifyAll(); //notify box is empty
}
Boy
synchronized void put() {
while (banana)
wait(); // wait for box empty
System.out.println(“put banana in”);
banana = true;
notifyAll(); // notify banana is ready
}
Monkey
Put
Get
Box
20
Example of Threads Coordination (Cont.)
class Monkey extends Thread {
Monkey(Box box) { this.box = box; }
public void run() {
while(true) {
box.get();
}
}
class Boy extends Thread {
Boy (Box box) { this.box = box; }
public void run() {
while(true){
box.put();
}
}
class MonkeyEatBanana {
public static void main(String args[]) {
Box box = new Box();
new Monkey (box).start();
new Boy (box).start(); }
}
Summary of producer-consumer
problem:
• define a class for the share objects,
with methods (synchronized if
necessary) for accessing the objects.
• define classes for producer threads and
consumer threads, using the methods
on the shared objects to access them.
• define a main routine which instantiates
shared objects and threads, and starts
the threads.
21
Download