ch2 - Threads & Synchronization
ch2 - Threads & Synchronization
PROGRAMMING
COURSE CODE : 223CCS-3
Understanding Threads
Creating Threads
Stopping a Thread
Thread Scheduling
Managing Threads
Synchronization
Synchronized Methods
3
2.2 CREATING THREADS
In Java, thread starts at the beginning of main(). Creating an additional thread
involves using an object of a class java.lang.Thread, or of a subclass of Thread.
To start the execution of a thread, call the start() method for the Thread object, and that
causes the run() method to be called, which is public, accepts no arguments, and doesn’t
return a value.
If we try to call the run() method directly ,then new thread will not be created.
We can define a class that is to represent a thread in two ways.
❑ One way is to define class as a subclass of Thread and provide a definition of the
method run(), which overrides the inherited method.
❑ Define class as implementing the interface Runnable, which declares the run()
method, and then create a Thread object in the class when needed.
A program that creates three threads is illustrated diagrammatically
4
2.2 CREATING THREADS(CONT…)
Daemon and User Threads
• A daemon thread is simply a background thread that is subordinate to the thread that
creates it, so when the thread that created the daemon thread ends, the daemon thread
dies with it.
• In this case, the method main() creates the daemon threads so that when main() returns,
all the threads it has created will also end.
• If you run the example a few times pressing Enter at random, you should see that the
daemon threads die after the main() method returns, because, from time to time,
you will get some output from one or other thread after the last output from main().
• A thread that isn’t a daemon thread is called a user thread.
5
// Method where thread execution will start
2.2 CREATING THREADS(CONT…)
public void run() {
PROGRAM 1: P1_TryThread.java try {
while(true) { // Loop indefinitely...
import java.io.IOException; System.out.print(fName);
public class P1_TryThread extends Thread { // Output first name
private String fName; // Store for first name sleep(aWhile);
private String sName; // Store for second name // Wait aWhile msec.
private long aWhile; // Delay in milliseconds System.out.print(sName + "\n");
// Output second name
public P1_TryThread(String fName, String sName, long delay) { }
this.fName = fName; // Store the first name } catch(InterruptedException e) {
this.sName = sName; // Store the second name // Handle thread interruption
aWhile = delay; // Store the delay
System.out.println(fName + sName + e);
setDaemon(true); // Thread is daemon
// Output the exception
}
public static void main(String[] args) { }
// Create three threads }
Thread t1 = new P1_TryThread("Asma ", "Mohamed ", 200L); }
Thread t2 = new P1_TryThread("Basma ", "Saeed ", 300L); OUTPUT OF PROGRAM 1:
Thread t3 = new P1_TryThread("Zeba ", "Ahmed ", 500L); Press Enter when you have had enough...
System.out.println("Press Enter when you have had enough...\n");
t1.start(); // Start the first thread Asma Basma Zeba Mohamed
t2.start(); // Start the second thread Asma
t3.start(); // Start the third thread Saeed
try { Basma Mohamed
System.in.read(); // Wait until Enter key pressed Asma Enter pressed...
System.out.println("Enter pressed...\n");
} catch (IOException e) { // Handle IO exception Ending main()
System.out.println(e); // Output the exception
}
Process completed.
System.out.println("Ending main()"); 6
return;
}
2.3 STOPPING A THREAD
A thread can signal another thread that it should stop executing by calling the interrupt()
method for that Thread object.
This in itself doesn’t stop the thread; it just sets a flag in the thread that indicates an
interruption has been requested. This flag must be checked in the run() method to have
any effect.
PROGRAM 2: P2_TryThread.java : User Thread
As Interrupt happens. The sleep() method checks whether the thread has been
interrupted, and throws an InterruptedException.
main() calls the interrupt() method for each of the threads after you press the Enter key,
the sleep() method that is called in each thread registers the fact that the thread has been
interrupted and throws an InterruptedException.
This is caught by the catch block in the run()method and produces the new output.
Because the catch block is outside the while loop,the run() method for each thread
returns and each thread terminates.
isInterrupted() method check whether a thread has been interrupted. It is an instance
method, you can use this in one thread to determine whether another thread has been
interrupted.
7
2.3 STOPPING A THREADS(CONT…) // Method where thread execution will start
public void run() {
PROGRAM 2: P2_TryThread.java try {
import java.io.IOException; while(true) { // Loop indefinitely...
public class P2_TryThread extends Thread { System.out.print(fName); // Output first name
private String fName; // Store for first name sleep(aWhile); // Wait aWhile msec.
private String sName; // Store for second name System.out.print(sName + "\n");
private long aWhile; // Delay in milliseconds
// Output second name
public P2_TryThread(String fName, String sName, long delay) {
}
this.fName = fName; // Store the first name
this.sName = sName; // Store the second name } catch(InterruptedException e) {
aWhile = delay; // Store the delay // Handle thread interruption
//setDaemon(true); // UserThread Not daemon Thread System.out.println(fName + sName + e);
} // Output the exception
public static void main(String[] args) { }
// Create three threads }
Thread t1 = new P2_TryThread("Asma ", "Mohamed ", 200L); }
Thread t2 = new P2_TryThread("Basma ", "Saeed ", 300L); OUTPUT OF PROGRAM 2:.
Thread t3 = new P2_TryThread("Zeba ", "Ahmed ", 500L); Press Enter when you have had enough...
System.out.println("Press Enter when you have had enough...\n");
t1.start(); // Start the first thread Asma Zeba Basma Mohamed
t2.start(); // Start the second thread Asma
t3.start(); // Start the third thread
Saeed
try {
Basma Mohamed
System.in.read(); // Wait until Enter key pressed
System.out.println("Enter pressed...\n"); Asma Enter pressed...
// Interrupt the threads
t1.interrupt(); Ending main()
t2.interrupt(); Asma Mohamed java.lang.InterruptedException: sleep
t3.interrupt(); interrupted
} catch (IOException e) { // Handle IO exception Basma Saeed java.lang.InterruptedException: sleep
System.out.println(e); // Output the exception interrupted
8
} Zeba Ahmed java.lang.InterruptedException: sleep
System.out.println("Ending main()"); interrupted
return;
} Process completed.
2.4 CONNECTING THREADS
(USING ISALIVE( ) AND JOIN( ))
Two ways exist to determine whether a thread has finished.
final boolean isAlive( ) The isAlive( ) method returns true if the thread upon which it is
called is still running. It returns false otherwise.
If one thread need to wait until another thread dies, you can call the join() method
Calling the join() method with no arguments will halt the current thread for as long as it
takes the specified thread to die:
thread1.join(); // Suspend the current thread until thread1 dies
A long value can also be passed to the join() method to specify the number of milliseconds
you’re prepared to wait for the death of a thread:
thread1.join(1000); // Wait up to 1 second for thread1 to die
The join() method can throw an InterruptedException if the current thread is interrupted
by another thread, so you should put a call to join() in a try block and catch the exception.
9
2.4 CONNECTING THREADS(CONT…) public void run() {
try {
PROGRAM 2A: P2_TryThreadA.java for(int i = 0;i<=2;i++){
import java.io.IOException; System.out.println(fName); // Output first name
public class P2_TryThreadA extends Thread { sleep(1000); // Wait for 1 sec
private String fName; // Store for first name }
public P2_TryThreadA(String fName) { } catch(InterruptedException e) { // Handle thread
this.fName = fName; // Store the first name interruption
//setDaemon(true); // UserThread Not daemon Thread
System.out.println(fName + e); // Output the
}
exception
public static void main(String[] args) {
}
// Create three threads
Thread t1 = new P2_TryThreadA("Asma "); }
Thread t2 = new P2_TryThreadA("Basma "); }
Thread t3 = new P2_TryThreadA("Zeba "); OUTPUT OF PROGRAM 2A:.
t1.start(); // Start the first thread Thread One is Alive :true
t2.start(); // Start the second thread Thread Two is Alive :true
t3.start(); // Start the third thread Thread Three is Alive :true
System.out.println("Thread One is Alive :"+ t1.isAlive()); Waiting for Threads to finish
System.out.println("Thread Two is Alive :"+ t2.isAlive()); Basma
System.out.println("Thread Three is Alive :"+ t3.isAlive()); Asma
try { Zeba
System.out.println("Waiting for Threads to finish"); Zeba
t1.join(); Asma
t2.join();
Basma
t3.join();
Basma
} catch (InterruptedException e) { // Handle Interrupted exception
System.out.println("Main thread Interrupted : " + e); Zeba
} Asma
System.out.println("Thread One is Alive :"+ t1.isAlive()); Thread One is Alive :false
System.out.println("Thread Two is Alive :"+ t2.isAlive()); Thread Two is Alive :false
System.out.println("Thread Three is Alive :"+ t3.isAlive()); Thread Three is Alive :false
1
Main Thread Exiting
System.out.println("Main Thread Exiting");
0
return; Process completed.
}
2.5 THREAD SCHEDULING
Each thread will certainly get a chance to execute while the others are “asleep,” that is,
when they’ve called their sleep() methods.
If Operating system uses preemptive multitasking, the program will work without the
call to sleep() in the run() method (remove the try and catch blocks when we remove the
sleep()).
If your operating system schedule without the sleep() call in run(), the first thread will hog
the processor and continue indefinitely.
yield(), defined in the Thread class, that gives other threads a chance to execute.
Calling yield(), causes the current thread to resume immediately if no threads are
waiting.
11
EXAMPLES FOR MULTITHREADING
PROGRAM 3: P3_MultiThread.java
// MultiThread : Understand Start() and run()with 2 Thread
public class P3_MultiThread extends Thread
{
public void run(){
for (int i=0;i<5;i++){
System.out.println(i);
try { OUTPUT OF PROGRAM 3:
Thread.sleep(1000); 0
}catch (InterruptedException e){ 0
} 1
1
} 2
} 2
public static void main( String[] args){ 3
Thread t1 = new P3_MultiThread(); 3
Thread t2 = new P3_MultiThread(); 4
// (or) 4
//P3_MultiThread t1 = new P3_MultiThread();
Process completed.
//P3_MultiThread t2 = new P3_MultiThread();
// 2 Thread Count 0 to 4 at same time, Multi thread excecutes
t1.start();
t2.start();
// No Multithread 2 :Thread 1 counts 0 to 4 then Thread 2 counts 0 to 4
//for Multithreading Use start() not run() 12
// t1.run();
// t2.run();
}
EXAMPLES FOR MULTITHREADING
PROGRAM 4: P4_MultiThread.java OUTPUT OF PROGRAM 4:
0
// MultiThread : Five Threads counting 0 to 4 0
public class P4_MultiThread extends Thread 0
{ 0
0
public void run(){
1
for (int i=0;i<5;i++){ 1
System.out.println(i); 1
try { 1
Thread.sleep(1000); 1
}catch (InterruptedException e){ 2
2
}
2
} 2
} 2
public static void main( String[] args){ 3
// Five thread Counting 0 to 4 3
for (int i=0;i<5;i++){ 3
Thread t1 = new P4_MultiThread(); 3
3
//(or)
4
//P4_MultiThread t1 = new P4_MultiThread(); 4
t1.start(); 4
} 4
} 4
} 13
Process completed.
EXAMPLES FOR MULTITHREADING
PROGRAM 5: P5_MultiThread.java
// MultiThread : Printing Thread Numbers of Five Threads counting 0 to 4 OUTPUT OF PROGRAM 5:
0 from Thread 0
// Order in which thread executes is unpredictable
0 from Thread 3
public class P5_MultiThread extends Thread 0 from Thread 4
{ 0 from Thread 1
private int tno; 0 from Thread 2
public P5_MultiThread(int tno) 1 from Thread 4
{ 1 from Thread 0
this.tno = tno; 1 from Thread 2
1 from Thread 3
}
1 from Thread 1
public void run(){ 2 from Thread 3
for (int i=0;i<5;i++){ 2 from Thread 4
System.out.println(i+ " from Thread " + tno); 2 from Thread 1
try { 2 from Thread 2
Thread.sleep(1000); 2 from Thread 0
3 from Thread 4
}catch (InterruptedException e){
3 from Thread 3
} 3 from Thread 2
} 3 from Thread 1
} 3 from Thread 0
public static void main( String[] args){ 4 from Thread 1
// Five thread Counting 0 to 4 4 from Thread 4
for (int i=0;i<5;i++){ 4 from Thread 2
4 from Thread 3
Thread t1 = new P5_MultiThread(i);
4 from Thread 0
//(or) 14
//P5_MultiThread t1 = new P5_MultiThread(i); Process completed.
t1.start();
} } }
EXAMPLES FOR MULTITHREADING
PROGRAM 6: P6_MultiThread.java
// MultiThread : Runtime Exception not affect other Thread OUTPUT OF PROGRAM 6:
public class P6_MultiThread extends Thread 0 from Thread 0
0 from Thread 1
{
0 from Thread 2
private int tno; 0 from Thread 3
public P6_MultiThread(int tno) 0 from Thread 4
{ Exception in thread "Thread-3"
this.tno = tno; java.lang.RuntimeException
} at
P6_MultiThread.run(P6_MultiThread.java:14)
public void run(){ 1 from Thread 0
for (int i=0;i<5;i++){ 1 from Thread 4
System.out.println(i+ " from Thread " + tno); 1 from Thread 1
// If thread 3 then throw exception 1 from Thread 2
if (tno == 3) 2 from Thread 4
throw new RuntimeException(); 2 from Thread 0
2 from Thread 2
try {
2 from Thread 1
Thread.sleep(1000); 3 from Thread 0
}catch (InterruptedException e){ 3 from Thread 1
} } } 3 from Thread 4
public static void main( String[] args){ 3 from Thread 2
// Five thread Counting 0 to 4 4 from Thread 2
4 from Thread 0
for (int i=0;i<5;i++){
4 from Thread 1
Thread t1 = new P6_MultiThread(i); 4 from Thread 4
//(or) 15
//P6_MultiThread t1 = new P6_MultiThread(i); Process completed.
t1.start();
} } }
EXAMPLES FOR MULTITHREADING
PROGRAM 7: P7_MultiThread.java OUTPUT OF PROGRAM 7:
// MultiThread : Runtime Exception not affect other Thread Exception in thread "main" 0 from Thread 1
// even Runtime Exception in main thread not affect other thread java.lang.RuntimeException
0 from Thread 0
public class P7_MultiThread extends Thread
0 from Thread 2
{ at
private int tno; P7_MultiThread.main(P7_MultiThread.java:26)
public P7_MultiThread(int tno) { 0 from Thread 4
this.tno = tno; 0 from Thread 3
} 1 from Thread 0
1 from Thread 1
public void run(){
1 from Thread 3
for (int i=0;i<5;i++){ 1 from Thread 4
System.out.println(i+ " from Thread " + tno); 1 from Thread 2
try { 2 from Thread 2
Thread.sleep(1000); 2 from Thread 0
}catch (InterruptedException e){ 2 from Thread 1
2 from Thread 4
} } }
2 from Thread 3
public static void main( String[] args){ 3 from Thread 3
// Five thread Counting 1 to 5 3 from Thread 2
for (int i=0;i<5;i++){ 3 from Thread 0
Thread t1 = new P7_MultiThread(i); 3 from Thread 4
//(or) 3 from Thread 1
4 from Thread 0
//P7_MultiThread t1 = new P7_MultiThread(i);
4 from Thread 3
t1.start(); 4 from Thread 2
} 4 from Thread 1 16
throw new RuntimeException(); 4 from Thread 4
}
} Process completed.
2.6 IMPLEMENTING THE RUNNABLE INTERFACE
The Runnable interface declares only one method, run(), and this is the method that
will be executed when the thread is started. public static void main(String[] args) {
PROGRAM 8: P8_JumbleNames.java Thread t1 = new Thread(new
import java.io.IOException; P8_JumbleNames("Asma ", "Mohamed ", 200L));
public class P8_JumbleNames implements Runnable { Thread t2 = new Thread(new
private String fName; // Store for first name P8_JumbleNames("Basma ", "Saeed ", 300L));
private String sName; // Store for second name Thread t3 = new Thread(new
private long aWhile; // Delay in milliseconds P8_JumbleNames("Zeba ", "Ahmed ", 500L));
// Constructor t1.setDaemon(true);
public P8_JumbleNames(String fName, String sName, t2.setDaemon(true);
long delay) { t3.setDaemon(true);
this.fName = fName; // Store the first name System.out.println("Press Enter when you have had enough...\n");
this.sName = sName; // Store the second name t1.start(); // Start the first thread
aWhile = delay; // Store the delay t2.start(); // Start the second thread
} t3.start(); // Start the third thread
// Method where thread execution will start try {
public void run() { System.in.read(); // Wait until Enter key pressed
try { System.out.println("Enter pressed...\n");
while(true) { // Loop indefinitely... } catch (IOException e) { // Handle IO exception
System.out.print(fName); // Output first name System.out.println(e); // Output the exception
Thread.sleep(aWhile); // Wait aWhile msec. }
System.out.print(sName+"\n"); System.out.println("Ending main()");
// Output second name return;
} } }
} catch(InterruptedException e) { OUTPUT OF PROGRAM 8:
// Handle thread interruption Press Enter when you have had enough...
Asma Basma Zeba
System.out.println(fName + sName + e); / 17
// Output the exception Mohamed
} Asma Enter pressed...
} Ending main()
Process completed.
2.7 MANAGING THREADS
For example, imagine that a bank teller is crediting a check to an account and at the same
time the customer with that account is withdrawing some cash through an ATM. This
might happen in the following way:
The bank teller checks the balance of the customer’s account, which is $500.
The ATM asks for the account balance.
The teller adds the value of the check, $100, so the account balance is $600.
The ATM takes $50 off the balance of $500, so the account balance is $450.
The teller assigns the value of $600 to the account balance.
The ATM assigns the value $450 to the account balance.
Where two or more threads share a common resource, such as a file or a block of
memory, you’ll need to take steps to ensure that one thread doesn’t modify a resource
while that resource is still being used by another thread.
Having one thread update a record in a file while another thread is partway through
retrieving the same record is a recipe for disaster. One way of managing this sort of
situation is to use synchronization for the threads involved.
18
2.8 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.
Key to synchronization is the concept of the monitor. ‘
A monitor is an object that is used as a mutually exclusive lock. 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. All other threads
attempting to enter the locked monitor will be suspended until the first thread exits the monitor.
These other threads are said to be waiting for the monitor. A thread that owns a monitor can reenter
the same monitor if it so desires.
You can use synchronization to manage your threads of execution in two ways:
❑ You can manage code at the method level—This involves synchronizing methods.
❑ You can manage code at the block level—This uses synchronizing blocks.
23
2.9 COMMUNICATING BETWEEN THREADS(CONT…)
PROGRAM 12: P12_itc.java class T2 implements Runnable {
class Chat { Chat m;
boolean flag = false; String[] s2 = { "Hi", "I am good, what about you?", "Great!" };
public synchronized void Question(String msg) { public T2(Chat m2) {
if (flag) { this.m = m2;
try { new Thread(this, "Answer").start();
wait();
}
} catch (InterruptedException e) {
public void run() {
e.printStackTrace(); }
for (int i = 0; i < s2.length; i++) {
}
System.out.println(msg); m.Answer(s2[i]);
flag = true; notify(); }
} }
public synchronized void Answer(String msg) { }
if (!flag) { public class P12_itc {
try { public static void main(String[] args) {
wait(); Chat m = new Chat();
} catch (InterruptedException e) { new T1(m);
e.printStackTrace(); } new T2(m);
}
}
System.out.println(msg); flag = false; notify();
}
} }
OUTPUT OF PROGRAM 12:
class T1 implements Runnable {
Chat m; Hi
String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" }; How are you ?
public T1(Chat m1) { I am good, what about you?
this.m = m1; I am also doing fine!
new Thread(this, "Question").start(); Great!
}
public void run() { Process completed. 24
for (int i = 0; i < s1.length; i++) {
m.Question(s1[i]);
}
} }
2.10 THREAD PRIORITIES
Thread priorities are used by the thread scheduler to decide when each thread
should be allowed to run.
setPriority( ) set a thread’s priority as final void setPriority(int level)
The Value of Level can be
MIN_PRIORITY(1),MAX_PRIORITY(10) or default NORM_PRIORITY(5)
These priorities are defined as static final variables within Thread.
getPriority( ) get the current priority as final int getPriority( )
Ourthread Mythread Program
25
2.10 THREAD PRIORITIES(CONT…)
PROGRAM 13: P13_Thread_Priority.java
class P13_Thread_Priority extends Thread {
String name;
P13_Thread_Priority(String n){
super(n);
this.name = n;
}
public void run(){ }
public static void main(String s[]){
P13_Thread_Priority t1 = new P13_Thread_Priority("One");
System.out.println("Priority of Thread "+t1.getName()+" is = "+t1.getPriority());
t1.setPriority(Thread.MAX_PRIORITY);
System.out.println("Maximum Priority of Thread "+t1.getName()+" is = "+t1.getPriority());
t1.setPriority(Thread.MIN_PRIORITY);
System.out.println("Minimum Priority of Thread "+t1.getName()+" is = "+t1.getPriority());
t1.setPriority(Thread.NORM_PRIORITY);
System.out.println("Normal Priority of Thread "+t1.getName()+" is = "+t1.getPriority());
t1.setPriority(Thread.MAX_PRIORITY - Thread.MIN_PRIORITY);
System.out.println("Maximum - Minimum Priority of Thread "+t1.getName()+" is = "+t1.getPriority());
} }
t1.t.setPriority(Thread.MAX_PRIORITY);
System.out.println("Maximum Priority of Thread "+t1.t.getName()+" is = "+t1.t.getPriority());
t1.t.setPriority(Thread.MIN_PRIORITY);
System.out.println("Minimum Priority of Thread "+t1.t.getName()+" is = "+t1.t.getPriority());
t1.t.setPriority(Thread.NORM_PRIORITY);
System.out.println("Normal Priority of Thread "+t1.t.getName()+" is = "+t1.t.getPriority());
t1.t.setPriority(Thread.MAX_PRIORITY - Thread.MIN_PRIORITY);
System.out.println("Maximum - Minimum Priority of Thread "+t1.t.getName()+" is = "+t1.t.getPriority());
} }