Threads m1
Threads m1
What is a thread?
Sun defines a thread as a single sequential flow of control within a
program.
A threads is a sequence of lines of code that execute within a
process.
It is sometimes referred to as an execution context or a lightweight
process.
Thread based multitasking environments allow a single program to
perform two or more tasks simultaneously.
The thread in java is a realization of OS level thread. In other words,
the thread in java is created using native methods which in turn
create threads based on the OS.
2
Test your knowledge
3
Uses of threads in application
4
java.lang.Thread class
So far programs that we created used just one thread.
Java SE provides 2 classes for working with thread called Thread
and ThreadGroup.
When a Java Virtual Machine starts up, that is when an application
starts to execute, there is usually a single thread called main.
The main threads continues to execute until
exit() method is called
all threads (non-daemon threads) have died
A deamon thread is a special type of thread that runs in background.
When JVM exits, only remaining thread which will be running are
daemon threads. By default all the threads that are created in java are
non-daemon threads. More on this later
5
Printing main thread
public class ThreadTest{
public static void main(String s[])
{
System.out.println(“Hello”);
System.out.println(
Thread.currentThread().getName());
}
}
Prints : main
6
Thread class constructors
7
Creating Threads by extending
class SimpleThread extends Thread {
public void run(){
/* code that is executed when
thread executes */
}}
We override the run() method and put the code that needs to be
executed when the thread runs, in the run() method.
To call run method we call start() !
8
Starting a thread
Since SimpleThread inherits from the Thread class, start()
method of the Thread class gets inherited into the SimpleThread
class.
The start() method of the Thread class creates OS level thread.
After this it calls the run() method.
Since the run() method is overriden , run() method of the
SimpleThread is called.
9
Starting a thread
JSE
public class Thread{…
public void start(){ 1
// create OS level thread
// calls run();
}
public void run(){…}}
10
Example : create Thread through inheritance
The code below tests if the given number is prime or non-prime, even or
odd.
Thread no. 1 : user created thread that tests for prime or non-prime.
Thread no. 2 : main thread that tests for even or odd.
import java.util.*;
class PrimeOddThread extends Thread {
int num;
public static void main(String str[]){
PrimeOddThread c= new PrimeOddThread ();
Scanner scan= new Scanner(System.in);
int i=scan.nextInt();
c.num=i;
c.start();
if(c.odd())
System.out.println("Odd");
else System.out.println("Even");
}
11
public void run() {
if( prime())
System.out.println("Prime");
else System.out.println("Non-Prime");
}
public boolean prime(){
for(int i=2;i<num/2;i++){
if(num%i==0) return false;}
return true;}
public boolean odd(){
if(num%2==0) return false;
else return true;
}}
The code is likely to print : Even first and then Prime (if prime and even
number like 2 is entered)
But strictly speaking, one can never guarantee whether Even will be
printed or Prime first. It is totally up to the OS thread scheduler to
choose which thread to execute first. 12
Test your understanding
13
Problem with the first way – Using Runnable
The way the thread was created (in the previous example) thread
requires your class to inherit from Thread class.
This means that this class cannot inherit from any other class.
Another way to program threads is by implementing Runnable
interface.
Runnable interface has one method
public void run()
Second way to create thread is by
1. Creating a class that implements Runnable interface- that is
overriding the run()
2. Creating a Thread class instance and passing Runnable instance.
Recall the 2nd set of constructors of Thread
14
Understanding working with Runnable
class SimpleThreadR implements Runnable{
public void run(){…}
}
17
Example :create Thread using Runnable
import java.util.*;
class PrimeOddThread implements Runnable {
int num;
18
public void run() {
if( prime())
System.out.println("Prime");
else System.out.println("Non-Prime");
}
19
Naming Threads
Every thread is given a name. If you don‟t specify a name, a default name
will be created.
For example the main thread is named „main‟.
The default name of a user defined thread is „Thread-0‟ for the first thread
created, „Thread-1‟ for the second and so on.
To explicitly name the thread
Use constructor
Thread(Runnable target, String name) or
Thread(String name)
Or instance method
final void setName(String name)
What is the method used to get the name? What is the method used to
get the current thread? 20
Lifecycle of a thread
Thread life cycle begins when a new thread instance is created.
Then start() method on thread is called. Calling the start() method does
not mean that the thread runs immediately. There may be many threads
waiting to run. It is up to Thread scheduler of the OS to decide which
thread will run first. We can‟t control the scheduler from the java
program! So when we have several threads (of same priority), we
cannot determine which thread will run when.
Also, just because a series of threads are started in a particular order
doesn‟t mean they‟ll run in that order.
When start() method is called a new thread of execution starts (with a
new call stack).The thread moves from the new state to the ready state.
When the thread gets a chance to execute, its run() method will be called.
A thread may be blocked - waiting for a resource (like printer etc). Once
the thread gets the resource, it again moves to ready state.
21
Lifecycle
When a thread completes its run() method, the thread is considered dead.
final boolean isAlive() can be used to check if the thread is alive or
dead.
An attempt to start a dead thread throws IllegalThreadStateException
yield() After run()
method
start() run() completes
new ready running dead
sleep(), wait()
Waiting for IO device
Waiting /
Up to the thread scheduler to pick a thread Blocked
for execution from ready state.
22
Putting a thread to sleep
boolean b=s.odd();
if(b)
System.out.print(" and Odd");
else System.out.print("and Even");
}}
29
Thread priorities
32
Why threads synchronization?
1.Let us say we have an Account class which has withdraw and deposit
methods.
2.For each transaction (deposit or withdraw) a thread is created.
3.Let us visualize what happens when two people simultaneously
withdraw from the same account object .
4. Let us assume that there is Rs. 1000 in the account
37
Terms
If two threads access the same object and each calls a method that
changes the state of that object then data corruption could result.
This is called race condition.
Monitor is a block of code guarded by a mutual-exclusion semaphore
(mutex or intrinsic lock or monitor lock ). A thread that wants to enter
the monitor must have mutex.
Only one thread can own the mutex at a time. Other threads which
wants to enter the critical code must wait till the thread that acquired
mutex releases it.
In Java, every object has one and only one monitor and mutex
associated with it.
38
Solution to the Account problem
Thread A acquires mutex for the Account object and
calls withdraw(500)
Account
Thread B waits for A to release the mutex
Rs.1000
Thread A waits for the transaction to complete
Rs 500
Thread A updates the money to (1000-500)=500 and
releases the mutex
40
Correcting code using synchronized
41
Tell me how?
How does static synchronized method work?
When they are invoked, since a static method is associated with a
class, the thread acquires the monitor lock for the Class object
associated with the class.
Thus access to class's static fields is controlled by this lock. Note that a
lock on static method has no effect on any instances of that class.
43
Code leading to deadlock
44
// Lock resource 2
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2.
updating the balance "); }
}
} };
t1.start();
t2.start();
}
}
void method1(){
synchronized(resource1){
synchronized(resource2){
…}}
}
void method2(){
synchronized(resource1){
synchronized(resource2){
…}}
}
47
Sequencing locking
The predefined sequence must be carefully thought out.
Will this code always work?
public void transferMoney(Account fromAccount,
Account toAccount, double amt) {
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.bal>amt) {
fromAccount.debit(amt);
toAccount.credit(amt);
}
} } }
What if a transfer of money happens from account 111 to account 222
and at the same time a transfer of money happens from account 222 to
account 111? Do see the deadlock occurring?
49
Daemon threads
So far the threads that we have been creating are called foreground
threads. A program continues to execute as long as it has at least one
foreground (non-daemon) thread that is alive.
The daemon threads are also called service threads. They are used for
background processes that will continue only as long as the active
threads of the program are alive.
Daemon threads cease to execute when there are no non-daemon
threads alive because when VM detects that the only remaining threads
are daemon threads, it exits.
The threads we have seen so far are non-daemon.
Example: garbage collector thread is a daemon thread that runs with a
low priority.
final void setDaemon(boolean on) : must be called before the
thread is started.
boolean isDaemon() 50
Example for daemon threads
The code prints “"Have a nice day“ for as long as main methods runs.
The main method finishes execution after printing the last letter
O.
52
ThreadGroup
53
ThreadGroup Members
Constructors
ThreadGroup(String name)
ThreadGroup(ThreadGroup parent, String name)
final ThreadGroup getThreadGroup()
Is a method of Thread class that returns the thread group the calling
thread belongs to
Methods to enumerate:
int enumerate(Thread[] list)
int enumerate(Thread[] list, boolean recurse)
Methods with respect to the group
int activeCount()
ThreadGroup getParent()
String getName()
boolean parentOf(ThreadGroup g)
54
Thread constructors with ThreadGroup
55
Methods :threads as a group
int getMaxPriority()
void setMaxPriority(int pri)
void interrupt()
void destroy()
boolean isDaemon()
void setDaemon(boolean daemon )
void list() (Prints information about this thread group to the
standard output. )
56
class ThreadGroupDemo{
public static void main (String [] args){
ThreadGroup tg = new ThreadGroup ("group 1");
Thread t1 = new Thread (tg, "thread 1");
Thread t2 = new Thread (tg, "thread 2");
Thread t3 = new Thread (tg, "thread 3");
After the production of item, the Producer thread has to intimate the
thread or threads which are waiting for the production. The
production happens for a member of the an object.
But the producer instead of directly notifying all the threads, just
notifies the object. Since object has list of all waiting (consumer)
threads with it ( as a result of the wait calls), object awakens all the
consumer threads.
final void notify()
Wakes up a single thread that is waiting on this object's lock. The
choice is arbitrary .
final void notifyAll()
Wakes up all threads that are waiting on this object's lock.
60
Monitor
Now one every important thing to bear in mind is that both producer and
consumer thread have to own a monitor before producing or
consuming.
When wait() is called, the thread releases ownership of this monitor
and waits until another thread notifies. Therefore the waiting threads
has to wait until can re-obtain ownership of the monitor and resume
execution
When the thread that calls notify() the lock is not released.
Therefore the producer thread after producing calls wait() to
relinquishes the lock on the object to allow consumer to consume.
Similarly the consumer thread must notify the producer that it has
finished consuming by calling notify(). This awakens the producer
thread which is on wait(). 61
Exceptions thrown by wait and notify
62
Example: Producer/Consumer
Example has one producer thread (tree) and one consumer threads
(earthworm).
Producer produces random amount apples if the apple count is less than
100 and notifies the consumer. It then waits until apple count is <100.
Consumer consumes random amount of apples if apple count is equal to
or above the count needed and then notifies the producer. If the required
apples are not available it waits until producer notifies it.
(int)(Math.random()*100)+1 produces a double number between
0 and 100.
64
try{
int i=(int)(Math.random()*100)+1;
Thread.sleep(i*10); // time taken to produce apples
apples=apples+i;
System.out.println("Produced apples ="+ apples);
}catch(InterruptedException e){}
notifyAll();
}}
//Consumers calls this method
synchronized void consume(){
while(true){
int i=(int)(Math.random()*100)+1;
// consume only if there are enough apples
if(apples>0 && apples<i)
try{
System.out.println(Thread.currentThread().getName()
+" waiting for "+ (i-apples) +“ more apples");
wait();}catch(InterruptedException e){}
65
try{
System.out.println(Thread.currentThread().getName()+ "
busy eating "+ i +" apples");
Thread.sleep(i); // time taken to consume apples
apples=apples-i;}
catch(InterruptedException e){}
notify();}
}
}}
66
Sample output
Produced apples =91
Produced apples =164
Waiting for apples to be eaten
Worm busy eating 42 apples
Worm busy eating 27 apples
Worm busy eating 73 apples
Worm busy eating 17 apples
Worm waiting for 54 more apples
Produced apples =88
67
Test your understanding
68
Test your understanding
System.out.println(Thread.currentThread().getName()+
" busy eating "+ i +" apples");
Thread.sleep(i);
apples=apples-i;}
catch(InterruptedException e){}
notify();}}
69
Multiple producer and consumers
Similar to the problem in the previous case, even in case of multiple producers we
have similar problem.
Cases where there could be multiple consumer and producer, while loops are used
instead of if for verifying the condition.
Corrected code to allow multiple producer and consumer:
synchronized void produce(){
while(true){
if(apples>100)
while(apples>100){
try{
System.out.println("Waiting for apples to be eaten");
wait();}catch(InterruptedException e){}}
try{
int i=(int)(Math.random()*100)+1;
Thread.sleep(i*10);
apples=apples+i;
System.out.println("Produced apples ="+ apples);
}catch(InterruptedException e){}
notifyAll();}} 70
synchronized void consume(){
while(true){
int i=(int)(Math.random()*100)+1;
if(apples>0 && apples<i)
while (apples>0 && apples<i){
try{
int j=(i-apples);
System.out.println(Thread.currentThread().getName() +
" waiting for "+j+" more apples");
wait();}catch(InterruptedException e){}
}
try{
System.out.println(Thread.currentThread().getName()+
" busy eating "+ i +" apples");
Thread.sleep(i);
apples=apples-i;}
catch(InterruptedException e){}
notify();}}
71