Multithreading in Java
Multithreading in Java
2
Advantages of Multithreading
• Reactive systems – constantly monitoring
• More responsive to user input – GUI application can interrupt a
time-consuming task
• Server can handle multiple clients simultaneously
• Can take advantage of parallel processing
• Different processes do not share memory space.
• A thread can execute concurrently with other threads within a single
process.
• All threads managed by the JVM share memory space and can
communicate with each other.
A single threaded program
class ABC
{
….
public void main(..) begin
{
… body
..
} end
5
A Multithreaded Program
Main Thread
start
start start
Thread Thread
A Thread B
C
7
Multithreaded Server: For Serving Multiple
Clients Concurrently
Server
Threads
■ Internet
Client 2 Process
8
Modern Applications need Threads (ex1):
Editing and Printing documents in background.
Printing Thread
Editing Thread
9
Threads in Java
Creating threads in Java:
10
Threads in Java
Creating threads in Java:
• Extend java.lang.Thread class
• run() method must be overridden (similar to main method of sequential
program)
• run() is called when execution of the thread begins
• A thread terminates when run() returns
• start() method invokes run()
• Calling run() does not create a new thread
• Implement java.lang.Runnable interface
11
Threads in Java
Creating threads in Java:
• Extend java.lang.Thread class
• Implement java.lang.Runnable interface
• If already inheriting another class (i.e., JApplet)
• Single method: public void run()
• Thread class implements Runnable.
12
Thread States
13
Implementing Runnable
class Thread1 implements Runnable
{
public void run()
{
System.out.println("Hello");
}
}
class ThreadDemo
{
public static void main(String args[])
{
Thread1 ob1=new Thread1();
Thread t1=new Thread(ob1);
t1.start();
}
}
Write a program to create two threads from
the same method
class Thread1 implements Runnable
{
public void run()
{
System.out.println("Hello");
}
}
class ThreadDemo
{
public static void main(String args[])
{
Thread1 ob1=new Thread1();
Thread t1=new Thread(ob1);
t1.start();
Thread1 ob2=new Thread1();
Thread t2=new Thread(ob2);
t2.start();
}
}
Creating threads from multiple methods
class Thread1 implements Runnable
{
public void run()
{
System.out.println("Hello");
}
}
class Thread2 implements Runnable
{
public void run()
{
System.out.println("Hai");
}
}
class ThreadDemo
{
public static void main(String args[])
{
Thread1 ob1=new Thread1();
Thread t1=new Thread(ob1);
t1.start();
Thread2 ob2=new Thread2();
Thread t2=new Thread(ob2);
t2.start();
}
}
Write a program to print numbers 1 to 20 in
one thread and 21 to 40 in another thread
class thread1 implements Runnable
{
public void run()
{
for(int i=1;i<=20;i++)
{
System.out.println("Thread 1 : "+ i);
}
}
}
class thread2 implements Runnable
{
public void run()
{
for(int j=21;j<=40;j++)
System.out.println("Thread 2 : "+ j);
}
}
public class Demo_thread {
public static void main(String args[])
{
thread1 ob1=new thread1();
Thread tx=new Thread(ob1);
tx.start();
thread2 ob2=new thread2();
Thread ty=new Thread(ob2);
ty.start();
}
}
Extending Thread
class thread1 extends Thread
{
public void run()
{
for(int i=1;i<=20;i++)
{
System.out.println("Thread 1 : "+ i);
}
}
}
class thread2 extends Thread
{
public void run()
{
for(int j=21;j<=40;j++)
System.out.println("Thread 2 : "+ j);
}
}
public class Demo_Thread2 {
public static void main(String args[])
{
thread1 ob1=new thread1();
ob1.start();
thread2 ob2=new thread2();
ob2.start();
}
}
Java.lang.Thread class in Java
• Field
Following are the fields for java.lang.Thread class −
• static int MAX_PRIORITY − This is the maximum priority that a thread can
have.
• static int NORM_PRIORITY − This is the default priority that is assigned to a
thread.
Method & Description
static int activeCount()This method returns the number of active
threads in the current thread's thread group.
static Thread currentThread()This method returns a reference to the
currently executing thread object.
long getId()This method returns the identifier of this Thread.
String getName()This method returns this thread's name.
int getPriority()This method Returns this thread's priority.
State getState()This method returns the state of this thread.
boolean isAlive()This method tests if this thread is alive.
void join()Waits for this thread to die.
void run()If this thread was constructed using a separate Runnable run
object, then that Runnable object's run method is called; otherwise, this
method does nothing and returns
void setName(String name)This method changes the name of this thread to
be equal to the argument name.
void setPriority(int newPriority)This method changes the priority of this
thread.
static void sleep(long millis)This method causes the currently executing
thread to sleep (temporarily cease execution) for the specified number of
milliseconds, subject to the precision and accuracy of system timers and
schedulers.
static void sleep(long millis, int nanos)This method causes the currently
executing thread to sleep (cease execution) for the specified number of
milliseconds plus the specified number of nanoseconds, subject to the
precision and accuracy of system timers and schedulers.
void start()This method causes this thread to begin execution; the Java
Virtual Machine calls the run method of this thread.
Example 2
class thread1 extends Thread
{
public void run()
{
try
{
for(int i=11;i<=20;i++)
{
System.out.println("Thread 1 : "+ i);
Thread.sleep(100);
}
}
catch (InterruptedException e)
{
System.out.println(e);
}
}
}
class thread2 extends Thread
{
public void run()
{
try
{
for(int j=100;j<=200;j+=10)
System.out.println("Thread 2 : "+ j);
Thread.sleep(1000);
}
catch (InterruptedException e)
{
System.out.println(e);
}
}
}
class example_thread
{
public static void main(String args[])
{
thread1 ob1=new thread1();
ob1.start();
thread2 ob2=new thread2();
ob2.start();
try
{
for(int x=50;x<=100;x=x+10)
{
System.out.println("Main Thread : "+ x);
Thread.sleep(50);
}
}
catch (InterruptedException e)
{
System.out.println(e);
}
}
}
• Write a program to print even numbers and odd numbers from 1 to
100 in two different threads
• Write a program to perform selection sort and bubble sort of an array
in two different threads
Printing name and id of threads
class thread1 extends Thread
{
public void run()
{
System.out.println("Id of current thread:"+ Thread.currentThread().getId());
System.out.println("Name of current thread:"+ Thread.currentThread().getName());
}
}
public class Demo_Thread2 {
public static void main(String args[])
{
thread1 ob1=new thread1();
ob1.start();
}
}
Write a program to print id and name of two
threads
Using isAlive( ) and join( )
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
}
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.");
}
}
class DemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
System.out.println("Main thread exiting.");
}
}
Output
New thread: Three: 3
Thread[One,5,main] One: 2
New thread:
Thread[Two,5,main] Two: 2
New thread: Three: 2
Thread[Three,5,main] One: 1
Thread One is alive: true Two: 1
Thread Two is alive: true
Thread Three is alive: Three: 1
true Two exiting.
Waiting for threads to Three exiting.
finish. One exiting.
One: 5
Two: 5 Thread One is alive: false
Three: 5 Thread Two is alive: false
One: 4 Thread Three is alive: false
Two: 4 Main thread exiting.
Three: 4
One: 3
Two: 3
Thread Priorities
• Thread priorities are used by the thread scheduler to decide when
each thread should be allowed to run
• CPU time that a thread gets often depends on several factors besides
its priority
• A higher-priority thread can also preempt a lower-priority one.
• final void setPriority(int level) ---Thread
• level: MIN_PRIORITY -1
• : MAX_PRIORITY -10
• : NORM_PRIORITY -5
final int getPriority( )
Synchronization
• 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.
// This program is not synchronized
class Callme
{
void call()
{
for(int i=0;i<10;i++)
{
System.out.print(" "+i+" ");
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
}
}
}
class Caller implements Runnable
{
Callme target;
public Caller(Callme targ)
{
target = targ;
} Output
public void run() 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8
{
target.call(); 8 9 9 9
}
}
class Synch
{
public static void main(String args[])
{
Callme target = new Callme();
Caller ob1 = new Caller(target);
Thread t1=new Thread(ob1);
t1.start();
Caller ob2 = new Caller(target);
Thread t2=new Thread(ob2);
t2.start();
Caller ob3 = new Caller(target);
Thread t3=new Thread(ob3);
t3.start();
}
}
• By calling sleep( ), the call( ) method allows execution to switch to
another thread. This results in the mixed-up output of the three
threads. In this program, nothing exists to stop all three threads from
calling the same method, on the same object, at the same time. This
is known as a race condition, because the three threads are racing
each other to complete the method.
• Synchronization can be done in two ways
• Using Synchronized methods
• Using Synchronized statements
Using Synchronized Methods
• While a thread is inside a synchronized method, all other threads that try
to call it on the same instance have to wait. To fix that problem in previous
program, serialize access to call( ) method. That is restrict its access to only
one thread at a time. To do this call( )’s definition is preceded with the
keyword synchronized, as shown here:
class Callme
{
synchronized void call(String msg)
{
...
Example:
class Callme
{
synchronized void call()
{
for(int i=0;i<10;i++)
{
System.out.print(“ “+i+” “);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
}
}
}
class Caller implements Runnable
{
Callme target;
public Caller(Callme targ)
{ Output:
target = targ;
}
public void run() 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
{ 3 4 5 67 8 9
target.call();
}
}
class Synch
{
public static void main(String args[])
{
Callme target = new Callme();
Caller ob1 = new Caller(target);
Thread t1=new Thread(ob1);
t1.start();
Caller ob2 = new Caller(target);
Thread t2=new Thread(ob1);
t2.start();
Caller ob3 = new Caller(target);
Thread t3=new Thread(ob1);
t3.start();
}
}
Using the synchronized Statement
• Put calls to the methods defined by this class inside a synchronized
block.
synchronized(object)
{
// statements to be synchronized
}
Example:
class Callme
{
void call()
{
for(int i=0;i<10;i++)
{
System.out.println(i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
System.out.println(",");
}
}
}
class Caller implements Runnable
{
Callme target;
public Caller(Callme targ)
{
target = targ; Output:
}
public void run() 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
{ 6 7 8 9
synchronized(target){
target.call();}
}
}
class Synch
{
public static void main(String args[])
{
Callme target = new Callme();
Caller ob1 = new Caller(target);
Thread t1=new Thread(ob1);
t1.start();
Caller ob2 = new Caller(target);
Thread t2=new Thread(ob2);
t2.start();
Caller ob3 = new Caller(target);
Thread t3=new Thread(ob2);
t3.start();
}
}
Interthread Communication
• unconditionally blocked other threads from asynchronous access to
certain methods
• Used implicit monitors in Java objects
Wait(), notify() and notifyAll()
• wait( ) tells the calling thread to give up the monitor and go to sleep
until some other thread enters the same monitor and calls notify( ) or
notifyAll( ).
• 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.
// 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);
}
}
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++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
class PC {
public static void main(String args[])
Output
{ Put: 1
Got: 1
Q q = new Q(); Got: 1
Got: 1
new Producer(q); Got: 1
Got: 1
new Consumer(q); Put: 2
Put: 3
System.out.println("Press Control-C to stop."); Put: 4
} Put: 5
Put: 6
} Put: 7
Got: 7
// 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("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n)
{
while(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
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++);
}
}
}
class Consumer implements Runnable
{
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true)
{
q.get();
}
}
}
class PCFixed {
public static void main(String args[]) { Output
Q q = new Q(); Put: 1
Got: 1
new Producer(q); Put: 2
Got: 2
new Consumer(q); Put: 3
Got: 3
System.out.println("Press Control-C to stop."); Put: 4
Got: 4
} Put: 5
Got: 5
}