Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
24 views

Multithreaded Programming

Uploaded by

Pramod J
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Multithreaded Programming

Uploaded by

Pramod J
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 67

Multithreaded Programming

• A multithreaded program contains two or more parts that can run


concurrently.
• Each part of such a program is called a thread, and each thread
defines a separate path of execution. Multithreading is a
specialized
form of multitasking.
• There are two types of multitasking : process-based, thread-based.
• Processes-based multitasking is the feature that allows your
computer to run two or more programs concurrently.
• Ex : process-based multitasking enables you to run the Java
compiler at the same time when using a text editor.
• In thread-based multitasking a single program can perform two or
more tasks simultaneously.
• Ex : A text editor can format text at the same time that it is
GRNICA 2

printing.
The Thread Class and Runnable Interface
• Java’s multithreading system is built upon the Thread class and its
companion interface, Runnable.
• To create a new thread, your program will either extend Thread or
implement the Runnable interface.
• The Thread class defines several methods that help manage
threads.

GRNICA 3
The Main Thread
• When a Java program starts up, one thread begins running
immediately. This is usually called the main thread of our
program.
• The main thread is important for two reasons :
• It is the thread from which other “child” threads will be
spawned.
• Often, it must be the last thread to finish execution because it
performs various shutdown actions.
• Main thread can be controlled through a Thread object.
• To do so, we must obtain a reference to it by calling the method
currentThread(), a public static member of Thread.
GRNICA 4
class CurrentThreadDemo {
public static void main(String args[]) {
Changes the name of
Thread t = Thread.currentThread();
the thread from main
System.out.println("Current thread: " + t); to “My Thread”
t.setName("My Thread");
System.out.println("After name change: " + t);
try { 1.sleep method to pause.
for(int n = 5; n > 0; n--) { 2. The argument
System.out.println(n); specifies the delay in
Thread.sleep(1000); milliseconds.
} 3. It might throw an
} catch (InterruptedException e) { interrupted exception.
System.out.println("Main thread interrupted");
}
}
} GRNICA 5
The name of the thread, its
priority and the name of its
group.

Current thread: Thread[main,5,main]


After name change: Thread[My Thread,5,main]
5 Thread name
4 changed, 5 is the
3 default priority of any
2 thread, main is the
1 name of its group.
GRNICA 6
Creating a Thread
• We can create a thread by instantiating an object of type Thread.
• Java defines two ways in which you can create a runnable object:
• You can implement the Runnable interface.
• You can extend the Thread class.

Implementing Runnable
• The easiest way to create a thread is to create a class that
implements the Runnable interface.
•We can construct a thread on any object that implements the
Runnable interface. Runnable defines only one method called
run( ).

Usage : public void run()


GRNICA 7
• Inside run( ), we write the code for the new thread.
• It is important to understand that run( ) can call other methods, use
other classes, and declare variables just like the main thread.
• The only difference is that run( ) establishes the entry point for
another, concurrent thread of execution within our program. This
thread will end when run( ) returns.
• After we have created a class that implements Runnable, we will
instantiate an object of type Thread on an object of that class.
• Thread defines several constructors. The one that we will use first
is shown here:
• Thread (Runnable threadOb, String threadName)
• In this constructor, threadOb is an instance of a class that
implements the Runnable interface. This defines where execution
of the thread will begin. GRNICA 8
• The name of the new thread is specified by the threadName.
• Once created, the new thread will not start running until we call its
start( ) method, which is declared within Thread. Then, start()
executes a call to run( ).

class NewThread implements Runnable Indicates we want the


{ new thread to call the
Thread t; run() method.

NewThread()
{
t = new Thread(this, "Demo Thread"); // Create a new, second thread
System.out.println("Child thread: " +Starts
t); the execution of thread
t.start(); beginning at the run()
} method.

GRNICA 9
// This is the entry point for the second thread.
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
} GRNICA 10
class ThreadDemo {
public static void main(String args[])
{
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
GRNICA 11
}
Extending Thread
• The second way to create a thread is to create a new class that
extends Thread, and then to create an instance of that class.
• The extending class must override the run() method, which is the
entry point for the new thread.
• It must also call start() to begin the execution of new thread.

class NewThread extends Thread Invokes the Thread constructor :


{ Public Thread(String threadname)
NewThread()
{
super("Demo Thread"); // Create a new, second thread
System.out.println("Child thread: " + this);
start(); // Start the thread
}
GRNICA 12
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
GRNICA 13
class ExtendThread {
public static void main(String args[]) {
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
} GRNICA 14
Creating Multiple Threads
// Create multiple threads.
class NewThread implements Runnable
{
String name; // name of thread
Thread t;

NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}

GRNICA 15
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e)
{
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
GRNICA 16
class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread("One"); // start threads
new NewThread("Two");
new NewThread("Three");
try
{
Thread.sleep(10000);
} catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
} GRNICA 17
Using isAlive() and join()

• It is often useful to know when a thread has ended.


• To find out, two ways exist to determine whether a thread has
finished.
• First, we can call isAlive( ) on the thread. Its general form is
shown here:
final boolean isAlive( )
• The isAlive( ) method returns true if the thread upon which it is
called is still running. It returns false otherwise.
• Another way to wait for a thread to finish is to call join( ), shown
here:
final void join( ) throws InterruptedException
GRNICA 18
• This method waits until the thread on which it is called terminates.
• Additional forms of join( ) allow us to specify a maximum
amount of time that we want to wait for the specified thread to
terminate.

class MyThread implements Runnable


{
int count;
Thread t;
MyThread(String name) // Construct a new thread.
{
t = new Thread(this, name);
count = 0;
t.start(); // start the thread
}
GRNICA 19
public void run()
{
System.out.println(t.getName() + " starting.");
try {
do{
Thread.sleep(1000);
System.out.println("In " + t.getName() + ",
count is " + count);
count++;
} while(count < 10);
}
catch(InterruptedException exc)
{
System.out.println(t.getName() + " interrupted.");
}
System.out.println(t.getName() + " terminating.");
} GRNICA 20
}
class JoinThreads
{
public static void main(String args[])
{
System.out.println("Main thread starting.");
MyThread mt1 = new MyThread("Child #1");
MyThread mt2 = new MyThread("Child #2");
MyThread mt3 = new MyThread("Child #3");

System.out.println("Child one is alive:"


+mt1.t.isAlive());
System.out.println("Child two is alive:"
+mt2.t.isAlive());
System.out.println("Child three is alive:"
+mt3.t.isAlive());

GRNICA 21
try {
mt1.t.join();
mt2.t.join();
mt3.t.join();
}
catch(InterruptedException exc)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Child one is alive:" +mt1.t.isAlive());
System.out.println("Child two is alive:" +mt2.t.isAlive());
System.out.println("Child three is alive:" +mt3.t.isAlive());
System.out.println("Main thread ending.");
}
}

GRNICA 22
Thread Priorities
• Each thread has associated with it a priority setting. A thread’s
priority determines, in part, how much CPU time a thread receives.
• In general, low-priority threads receive little. High priority threads
receive a lot.
• It is important to understand that factors other than a thread’s
priority also affect how much CPU time a thread receives.
• When a child thread is started, its priority setting is equal to that of
its parent thread.
• You can change a thread’s priority by calling setPriority( ), which
is a member of Thread. This is its general form:
final void setPriority(int level)
GRNICA 23
• Here, level specifies the new priority setting for the calling thread.
• The value of level must be within the range MIN_PRIORITY and
MAX_PRIORITY.
• Currently, these values are 1 and 10, respectively. To return a thread
to default priority, specify NORM_PRIORITY, which is
currently 5.
• These priorities are defined as final variables within Thread.
• You can obtain the current priority setting by calling the
getPriority( ) method of Thread, shown here:

final int getPriority( )

GRNICA 24
class clicker implements Runnable
{
int click = 0;
Thread t;
private volatile boolean running = true;

public clicker(int p)
{ It is used to ensure that
t = new Thread(this); the value of running is
t.setPriority(p); examined each time the
} following loop iterates.

GRNICA 25
public void run()
{
while (running)
{
click++;
}
}
public void stop()
{
running = false;
}
public void start()
{
t.start();
}
} GRNICA 26
class HiLoPri
{
public static void main(String args[])
{
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
clicker hi = new clicker(Thread.MIN_PRIORITY + 3);
clicker lo = new clicker(Thread.MIN_PRIORITY + 1);
lo.start();
hi.start();
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
GRNICA 27
lo.stop();
hi.stop();

// Wait for child threads to terminate.


try
{
hi.t.join();
lo.t.join();
} catch (InterruptedException e)
{
System.out.println("InterruptedException caught");
}
System.out.println("Low-priority thread: " + lo.click);
System.out.println("High-priority thread: " + hi.click);
}
}
GRNICA 28
Synchronization
• When using multiple threads, it is sometimes necessary to
coordinate the activities of two or more.
• When two or more threads need access to a shared resource, they
need some way to ensure that the resource will be used by only one
thread at a time.
• The process by which this is achieved is called synchronization.
• Key to synchronization in Java is the concept of the monitor,
(semaphore).
• A monitor is an object that is used as a mutually exclusive lock, or
mutex. Only one thread can own a monitor at a given time.
• When a thread acquires a lock, it is said to have entered the monitor.
GRNICA 29
• All other threads attempting to enter the locked monitor will be
suspended until the first thread exits the monitor, and these other
threads are said to be waiting for the monitor.
• This feature is built into the Java language, itself. Thus, all objects
can be synchronized.
• Synchronization is supported by the keyword synchronized.
• Since synchronization was designed into Java from the start, it is
much easier to use than any other programming languages.

GRNICA 30
Using Synchronized Methods
• Synchronization is easy in Java, because all objects have their own
implicit monitor associated with them.

• To enter an object’s monitor, just call a method that has been


modified with the synchronized keyword.

• While a thread is inside a synchronized method, all other threads


that try to call it on the same instance have to wait.

• To exit the monitor and relinquish control of the object to the next
waiting thread, the owner of the monitor simply returns from the
synchronized method.

GRNICA 31
// this program is not synchronized
class Callme
{
void call(String msg)
{
System.out.print("[" + msg);
try
{
Thread.sleep(3000);
} catch (InterruptedException e)
{
System.out.println("Interrupted");
}
System.out.println("]");
}
}
GRNICA 32
class Caller implements Runnable
{
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run()
{
target.call(msg);
}
} GRNICA 33
class Synch{
public static void main(String args[])
{
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try
{
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
} GRNICA 34

}
The synchronized Statement
• Although creating synchronized methods within classes that we
create is an easy and effective means of achieving synchronization,
it will not work in all cases.
• For ex. You want to use a class that does not use synchronized
methods & this class is not created by you.
• Thus, it is not possible for you to add synchronized to the
appropriate methods within the class.
• How can access to an object of this class be synchronized?
• The solution is easy: You simply put calls to the methods defined
by this class inside a synchronized block.

GRNICA 35
• This is the general form of a synchronized block:
synchronized ( object )
{
// statements to be synchronized
}
• Here, object is a reference to the object being synchronized.
• A synchronized block ensures that a call to a method that is a
member of object will take place only after the object’s monitor has
been entered by the calling thread.

GRNICA 36
// Uses synchronized block.
class Callme
{
void call(String msg)
{
System.out.print("[" + msg);
try
{
Thread.sleep(3000);
} catch (InterruptedException e)
{
System.out.println("Interrupted");
}
System.out.println("]");
}
}
GRNICA 37
class Caller implements Runnable
{
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() { // synchronize calls to call()
synchronized (target) { // synchronized block
target.call(msg);
}
} GRNICA 38
}
class Synch1{
public static void main(String args[])
{
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try
{
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
} GRNICA 39

}
Interthread Communication
• Consider the following situation. A thread called T is executing
inside a synchronized method and needs access to a resource
called R that is temporarily unavailable.
• What should T do? If T enters some form of polling loop that waits
for R, T ties up the object, preventing other threads’ access to it &
wastes the CPU time.
• A better solution is to have T temporarily relinquish control of the
object, allowing another thread to run. When R becomes available,
T can be notified and resume execution.
• Such an approach relies upon some form of interthread
communication in which one thread can notify another that it is
blocked, and be notified that it can resume execution.
GRNICA 40
• Java supports interthread communication with the wait( ), notify( ),
and notifyAll( ) methods.
• wait() tells the calling thread to give up the monitor and go to
sleep until some other thread enters the same monitor & calls
notify().
• notify() wakes up a thread that called wait() on the same object.
• notifyAll() wakes up all the threads that called wait() on the
same object. One of the threads will be granted access.

• Note : Although wait() normally waits until notify() / notifyAll()


is called, but rarely the waiting thread could be awakened due to a
spurious wakeup.
• In this case, a waiting thread resumes without notify()/notifyAll()
having been called.
GRNICA 41
• Hence, Sun recommends that calls to wait() should take place
within a loop that checks the condition on which the thread is
waiting.

GRNICA 42
// An incorrect implementation of a producer and consumer.
class Q {
int n;

synchronized int get() {


System.out.println("Got: " + n);
return n;
}

synchronized void put(int n) {


this.n = n;
System.out.println("Put: " + n);
}
}

GRNICA 43
class Producer implements Runnable {
Q q;

Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}

public void run() {


int i = 0;

while(true) {
q.put(i++);
}
}
}
GRNICA 44
class Consumer implements Runnable {
Q q;

Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}

public void run() {


while(true) {
q.get();
}
}
}

GRNICA 45
class PC {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);

System.out.println("Press Control-C to stop.");


}
}

GRNICA 46
//A correct implementation of a producer and consumer.
class Q
{
int n;
boolean valueSet = false;
synchronized int get()
{
while(!valueSet)
try
{
wait();
} catch(InterruptedException e) {}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
} GRNICA 47
synchronized void put(int n)
{
while(valueSet)
try
{
wait();
} catch(InterruptedException e) {}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}

GRNICA 48
class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q = q;
new Thread(this, "Producer").start();
}
public void run()
{
int i = 0;
while(true)
{
q.put(i++);
}
}
} GRNICA 49
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
GRNICA 50
class PCFixed
{
public static void main(String args[])
{
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}

GRNICA 51
Deaklock
• A special type of error that you need to avoid that relates
specifically to multitasking is deadlock, which occurs when two
threads have a circular dependency on a pair of synchronized objects.
• Deadlock is a difficult error to debug for two reasons:
• In general, it occurs only rarely, when the two threads time-
slice
in just the right way.
• It may involve more than two and two synchronized objects.

GRNICA 52
class A
{
synchronized void foo(B b)
{
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try
{
Thread.sleep(1000);
} catch(Exception e) {}
System.out.println(name + " trying to call B.last()");
b.last();
}
synchronized void last()
{
System.out.println("Inside A.last");
}
GRNICA 53
}
class B
{
synchronized void bar(A a)
{
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try
{
Thread.sleep(1000);
} catch(Exception e) {}
System.out.println(name + " trying to call A.last()");
a.last();
}
synchronized void last()
{
System.out.println("Inside A.last");
} GRNICA 54
}
class Deadlock implements Runnable
{
A a = new A();
B b = new B();

Deadlock()
{
Thread.currentThread().setName("MainThread");
Thread t = new Thread(this, "RacingThread");
t.start();

a.foo(b); // get lock on a in this thread.


System.out.println("Back in main thread");
}

GRNICA 55
public void run()
{
b.bar(a); // get lock on b in other thread.
System.out.println("Back in other thread");
}

public static void main(String args[])


{
new Deadlock();
}
}

GRNICA 56
Suspending, Resuming, and Stopping Threads
Using Java 1.1 and Earlier

• It is sometimes useful to suspend execution of a thread. For


example, a separate thread can be used to display the time of day.
• If the user does not desire a clock, then its thread can be
suspended. It is a simple matter to suspend a thread. Once
suspended, it is also a simple matter to restart the thread.
• In older versions of Java a program used suspend( ), resume( ),
and stop( ), which are methods defined by Thread, to pause,
restart,
and stop the execution of a thread.

GRNICA 57
class NewThread implements Runnable
{
String name; // name of thread
Thread t;

NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}

GRNICA 58
// This is the entry point for thread.
public void run()
{
try
{
for(int i = 15; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(200);
}
} catch (InterruptedException e) {}
System.out.println(name + " exiting.");
}
}

GRNICA 59
class SuspendResume
{
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.t.suspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.t.resume();
System.out.println("Resuming thread One");
ob2.t.suspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.t.resume();
System.out.println("Resuming
GRNICA
thread Two"); 60

} catch (InterruptedException e) {}
// wait for threads to finish
try
{
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {}
System.out.println("Main thread exiting.");
}
}

GRNICA 61
Suspending, Resuming, and Stopping Threads
Using Java 2
• The suspend( ) method of the Thread class is deprecated in Java
2. This was done because suspend( ) can sometimes cause serious
system failures.
• The resume( ) method is also deprecated. It does not cause
problems, but cannot be used without the suspend( ) method as its
counterpart.
• The stop( ) method of the Thread class, too, is deprecated in Java
2. This was done because this method can sometimes cause serious
system failures.

• Because you can’t use the suspend( ), resume( ), or stop( ) methods


in Java 2 to control a thread, you might be thinking that no way exists
to pause, restart, or terminate a thread.
GRNICA 62
• Instead, a thread must be designed so that the run( ) method
periodically checks to determine whether that thread should
suspend, resume, or stop its own execution.
• Typically, this is accomplished by establishing a flag variable that
indicates the execution state of the thread. As long as this flag is set
to “running,” the run( ) method must continue to let the thread
execute.
• If this variable is set to “suspend,” the thread must pause. If it is set
to “stop,” the thread must terminate.

GRNICA 63
// Suspending and resuming a thread for Java 2
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}

GRNICA 64
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
} GRNICA 65
void mysuspend(){
suspendFlag = true;}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
GRNICA 66

System.out.println("Resuming thread One");


ob2.mysuspend();
System.out.println("Suspending thread
Two");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try{
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
} GRNICA 67

System.out.println("Main thread exiting.");}

You might also like