0% found this document useful (0 votes)
39 views91 pages

CH 6

Uploaded by

jsjshdhdhdhdh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views91 pages

CH 6

Uploaded by

jsjshdhdhdhdh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 91

CH-6

Multithreading

Prepared By: Fatema Vhora


Topics
• Multithreading: Multi-Threading and Multitasking;
• Thread Life Cycle,
• thread states,
• creating threads: Thread Priorities,
• Thread Groups,
• Daemon Threads,
• interrupting threads,
• thread priorities;
• Synchronizing threads,
• inter-thread communication
Multitasking
• Multitasking is when a CPU is provided to execute multiple tasks at a
time. Multitasking involves often CPU switching between the tasks, so
that users can collaborate with each program together. Unlike
multithreading, In multitasking, the processes share separate
memory and resources. As multitasking involves CPU switching
between the tasks rapidly, So the little time is needed in order to
switch from the one user to next
Multithreading:
• Multithreading is a system in which many threads are created from a
process through which the computer power is increased. In
multithreading, CPU is provided in order to execute many threads
from a process at a time, and in multithreading, process creation is
performed according to cost. Unlike multitasking, multithreading
provides the same memory and resources to the processes for
execution.
Thread
• Threads allows a program to operate more efficiently by doing
multiple things at the same time.
• Threads can be used to perform complicated tasks in the background
without interrupting the main program.
• 1. Parallel Programming
• One of the main reasons to use threads in Java is to make a task run
parallel to another task like drawing and event handling.GUI
applications e.g. SWING and JAVA FX GUIs are the best examples of
multi-threading in Java.
• 2. To take full advantage of CPU power.
• Another common reason for using multiple threads in Java is to
improve the throughput of the application by utilizing full CPU power.
For example, if you have got 32 core CPUs and you are only using 1 of
them for serving 1000 clients and assuming that your application is
CPU bound, you can improve throughput to 32 times by using 32
threads, which will utilize all 32 cores of your CPU.
• 3. For reducing response time
• You can also use multiple threads to reduce response time by doing
fast computation by dividing a big problem into smaller chunks and
processing them by using multiple threads. For example, the map-
reduce pattern is based upon dividing a big problem into smaller ones
and processing them individually, Java also provides FORK-JOIN
Thread Pool for just that purpose.
• 4. To serve multiple clients at the same time.
• One of the most common scenarios where using multiple threads
significantly improves an application's performance is a client-server
application. A single-threaded application means only one client can
connect to the server at a time, but a multi-threaded server means
multiple clients can connect to the server at the same time.
• In Java, a thread always exists in any one of the following states.
These states are:
• New
• Active
• Blocked / Waiting
• Timed Waiting
• Terminated
• New: Whenever a new thread is created, it is always in the new state. For a
thread in the new state, the code has not been run yet and thus has not begun
its execution.
• Active: When a thread invokes the start() method, it moves from the new state
to the active state. The active state contains two states within it: one is runnable,
and the other is running.
• Runnable: A thread, that is ready to run is then moved to the runnable state. In the
runnable state, the thread may be running or may be ready to run at any given instant of
time. It is the duty of the thread scheduler to provide the thread time to run, i.e., moving
the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each individual
thread. Each and every thread runs for a short span of time and when that allocated time
slice is over, the thread voluntarily gives up the CPU to the other thread, so that the other
threads can also run for their slice of time. Whenever such a scenario occurs, all those
threads that are willing to run, waiting for their turn to run, lie in the runnable state. In the
runnable state, there is a queue where the threads lie.
• Running: When the thread gets the CPU, it moves from the runnable to the running state.
Generally, the most common change in the state of a thread is from runnable to running
and again back to runnable.
• Blocked or Waiting: Whenever a thread is inactive for a span of time
(not permanently) then, either the thread is in the blocked state or is
in the waiting state.
• For example, a thread (let's say its name is A) may want to print some data from the
printer. However, at the same time, the other thread (let's say its name is B) is using the
printer to print some data. Therefore, thread A has to wait for thread B to use the printer.
Thus, thread A is in the blocked state. A thread in the blocked state is unable to perform
any execution and thus never consume any cycle of the Central Processing Unit (CPU).
Hence, we can say that thread A remains idle until the thread scheduler reactivates
thread A, which is in the waiting or blocked state.
• When the main thread invokes the join() method then, it is said that the main thread is in
the waiting state. The main thread then waits for the child threads to complete their
tasks. When the child threads complete their job, a notification is sent to the main
thread, which again moves the thread from waiting to the active state.
• If there are a lot of threads in the waiting or blocked state, then it is the duty of the
thread scheduler to determine which thread to choose and which one to reject, and the
chosen thread is then given the opportunity to run.
• Timed Waiting: Sometimes, waiting for leads to starvation. For
example, a thread (its name is A) has entered the critical section of a
code and is not willing to leave that critical section. In such a scenario,
another thread (its name is B) has to wait forever, which leads to
starvation. To avoid such scenario, a timed waiting state is given to
thread B. Thus, thread lies in the waiting state for a specific span of
time, and not forever. A real example of timed waiting is when we
invoke the sleep() method on a specific thread. The sleep() method
puts the thread in the timed wait state. After the time runs out, the
thread wakes up and start its execution from when it has left earlier.
• Terminated: A thread reaches the termination state because of the
following reasons:
• When a thread has finished its job, then it exists or terminates
normally.
• Abnormal termination: It occurs when some unusual events such as
an unhandled exception or segmentation fault.
• A terminated thread means the thread is no more in the system. In
other words, the thread is dead, and there is no way one can respawn
(active after kill) the dead thread.
Implementation of Thread States
• In Java, one can get the current state of a thread using
the Thread.getState() method
• public static final Thread.State NEW

• public static final Thread.State RUNNABLE

• public static final Thread.State BLOCKED

• public static final Thread.State WAITING


Thread state
How to create a thread in Java
• There are two ways to create a thread:
• By extending Thread class
• By implementing Runnable interface.
• Thread class:
• Thread class provide constructors and methods to create and perform
operations on a thread.Thread class extends Object class and
implements Runnable interface.
• You can create threads by implementing the runnable interface and overriding the run() method. Then, you can create a thread object and
call the start() method.

• Thread Class:

• The Thread class provides constructors and methods for creating and operating on threads. The thread extends the Object and implements
the Runnable interface.

• // start a newly created thread.


• // Thread moves from new state to runnable state
• // When it gets a chance, executes the target run() method
• public void start()
• Runnable interface:

• Any class with instances that are intended to be executed by a thread should implement the Runnable interface. The Runnable interface has
only one method, which is called run().

• // Thread action is performed


• public void run()
• Calling run() instead of start()

• The common mistake is starting a thread using run() instead of start()


method.

• Thread myThread = new Thread(MyRunnable());


• myThread.run(); //should be start();

• The run() method is not called by the thread you created. Instead, it is
called by the thread that created the class.
• Commonly used Constructors of Thread class:
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r,String name)

Commonly used methods of Thread class:

• public void run(): is used to perform action for a thread.


• public void start(): starts the execution of the thread.JVM calls the
run() method on the thread.
• public void sleep(long miliseconds): Causes the currently executing
thread to sleep (temporarily cease execution) for the specified
number of milliseconds.
Runnable interface:
• The Runnable interface should be implemented by any class whose
instances are intended to be executed by a thread. Runnable interface
have only one method named run().
• public void run(): is used to perform action for a thread.
• Starting a thread:
• The start() method of Thread class is used to start a newly created
thread. It performs the following tasks:
• A new thread starts(with new callstack).
• The thread moves from New state to the Runnable state.
• When the thread gets a chance to execute, its target run() method
will run.
Java Thread Example by extending Thread
class
• class Multi extends Thread{
• public void run(){
• System.out.println("thread is running...");
•}
• public static void main(String args[]){
• Multi t1=new Multi();
• t1.start();
• }
•}
Java Thread Example by implementing
Runnable interface
• class Multi3 implements Runnable{
• public void run(){
• System.out.println("thread is running...");
• }

• public static void main(String args[]){
• Multi3 m1=new Multi3();
• Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
• t1.start();
• }
• }
Start vs run method
• Main difference is that when program calls start() method a new
Thread is created and code inside run() method is executed in new
Thread while if you call run() method directly no new Thread is
created and code inside run() will execute on current Thread. Most of
the time calling run() is bug or programming mistake because the
caller has the intention of calling start() to create a new thread and
this error can be detected by many static code coverage tools like find
bugs.
• Another difference between start vs run in Java thread is that
you can not call start() method twice on the thread object. once
started, the second call of start() will throw IllegalStateException in
Java while you can call run() method twice.
Question: Can we call the run method directly from the Main method?
Yes, we can call the run method directly. If we call it directly then a user-defined thread in the java stack area
is not created. It is executed in the main thread.
public class MyThread extends Thread
{
public void run ()
{
for (int i = 0; i <= 50; i++)
{
System.out.println ("Run: " + i);
}
}
public static void main (String[]args)
{
MyThread mt = new MyThread ();
mt.run ();
for (int i = 0; i <= 50; i++)
{
System.out.println ("Main: " + i);
}
}
}
What will be the output in the below program?
public class Main extends Thread
{
public void run ()
{
for (int i = 0; i <= 50; i++)
{
System.out.println ("Run: " + i);
}
}
public static void main (String[]args)
{
Main mt = new Main();
mt.run();
mt.start();
for (int i = 0; i <= 50; i++)
{
System.out.println ("Main: " + i);
}
}
}
first run method in the main thread completes its execution, then due to the start method call user-
defined thread is created and the run method is also again. Now run method in the user-defined
thread and the main method for loop in the main thread are executed concurrently.
public class Main extends Thread
{
public void run ()
{
for (int i = 0; i <= 5; i++)
{
System.out.println ("Run: " + i);
}
}
public static void main (String[]args)
{
Main mt = new Main();
mt.start ();
mt.run ();
for (int i = 0; i <= 5; i++)
{
System.out.println ("Main: " + i);
}
}
}
If we call the Run method from the Overriding start
method then in which thread the run method is
going to be executed?
public class MyThread extends Thread
{
public void run ()
{
System.out.println ("run");
}
public void start ()
{
System.out.println ("start");
run();
}
public static void main (String args[])
{
MyThread mt = new MyThread ();
mt.start ();
System.out.println ("main");
}
}
Can we call the start method more than once
on the same thread object?
public class Main extends Thread
{
public void run ()
{
for (int i = 0; i <= 50; i++)
{
System.out.println ("Run: " + i);
}
}
public static void main (String[]args)
{
Main mt = new Main();
mt.start ();
mt.start ();
for (int i = 0; i <= 50; i++)
{
System.out.println ("Main: " + i);
}
}
}
Thread interference and memory consistency errors can be avoided by
ensuring the following two things-

1.Only one thread can read and write a shared variable at a time. When one
thread is accessing a shared variable, other threads should wait until the first
thread is done. This guarantees that the access to a shared variable is Atomic,
and multiple threads do not interfere.

2. Whenever any thread modifies a shared variable, it automatically


establishes a happens-before relationship with subsequent reads and writes of
the shared variable by other threads. This guarantees that changes done by
one thread are visible to others.

Volatile and synchronized keywords are used for interference and memory
consistency error control
java.lang.Runnable is an interface that is to be implemented by a class whose
instances are intended to be executed by a thread. There are two ways to start a
new Thread – Subclass Thread and implement Runnable. There is no need of
subclassing a Thread when a task can be done by overriding only run() method of
Runnable.
public class RunnableDemo {

public static void main(String[] args)


{
System.out.println("Main thread is- "
+
Thread.currentThread().getName());
Thread t1 = new Thread(new RunnableDemo().new RunnableImpl());
t1.start();
}

private class RunnableImpl implements Runnable {

public void run()


{
System.out.println(Thread.currentThread().getName()
+ ", executing run()
method!");
}
}
} Main thread is- main
Thread-0, executing run() method!
The output shows two active threads in the program – main thread and Thread-0, main method is
executed by the Main thread but invoking the start on RunnableImpl creates and starts a new thread –
Thread-0. What happens when Runnable encounters an exception ? Runnable can’t throw checked
exception but RuntimeException can be thrown from the run(). Uncaught exceptions are handled by the
exception handler of the thread, if JVM can’t handle or catch exceptions, it prints the stack trace and
terminates the flow

The printStackTrace() method in Java is a tool used to handle


exceptions and errors. It is a method of Java’s throwable class
which prints the throwable along with other details like the line
number and class name where the exception occurred.

printStackTrace() is very useful in diagnosing exceptions. For


example, if one out of five methods in your code cause an
exception, printStackTrace() will pinpoint the exact line in
which the method raised the exception.
Thread Priority
// Importing the required classes // We did not mention the priority of the thread.
import java.lang.*; // Therefore, the priorities of the thread is 5, the default valu

public class ThreadPriorityExample extends Thread // 1st Thread


{ // Displaying the priority of the thread
// using the getPriority() method
// Method 1 System.out.println("Priority of the thread th1 is : " +
// Whenever the start() method is called by a thread th1.getPriority());
// the run() method is invoked
public void run() // 2nd Thread
{ // Display the priority of the thread
// the print statement System.out.println("Priority of the thread th2 is : " +
System.out.println("Inside the run() method"); th2.getPriority());
}
// 3rd Thread
// the main method // // Display the priority of the thread
public static void main(String argvs[]) System.out.println("Priority of the thread th2 is : " +
{ th2.getPriority());
// Creating threads with the help of ThreadPriorityExample
class // Setting priorities of above threads by
ThreadPriorityExample th1 = new ThreadPriorityExample(); // passing integer arguments
ThreadPriorityExample th2 = new ThreadPriorityExample(); th1.setPriority(6);
ThreadPriorityExample th3 = new ThreadPriorityExample(); th2.setPriority(3);
th3.setPriority(9);
// 6
System.out.println("Priority of the thread th1 is : " + th1.getPriority());

// 3
System.out.println("Priority of the thread th2 is : " + th2.getPriority());

// 9
System.out.println("Priority of the thread th3 is : " + th3.getPriority());

// Main thread

// Displaying name of the currently executing thread


System.out.println("Currently Executing The Thread : " + Thread.currentThread().getName());

System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());

// Priority of the main thread is 10 now


Thread.currentThread().setPriority(10);

System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());


}
}
If there are two threads that have the same priority, then one can not predict
which thread will get the chance to execute first. The execution then is dependent
on the thread scheduler's algorithm (First Come First Serve, Round-Robin, etc.)
Thread Groups
public class ThreadGroupDemo implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadGroupDemo runnable = new ThreadGroupDemo();
ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");

Thread t1 = new Thread(tg1, runnable,"one");


t1.start();
Thread t2 = new Thread(tg1, runnable,"two");
t2.start();
Thread t3 = new Thread(tg1, runnable,"three");
t3.start();
System.out.println("Thread Group Name: "+tg1.getName());
tg1.list();

}
}
N Constructor Description
o.
1) ThreadGroup(String name) creates a thread group with given name.
2) ThreadGroup(ThreadGroup parent, creates a thread group with a given parent group and name.
String name)
Daemon Threads
A Daemon thread is a background service thread which runs as a low priority
thread and performs background operations like garbage collection. JVM
exits if only daemon threads are remaining.

The setDaemon() method of the Thread class is used to mark/set a particular


thread as either a daemon thread or a user thread. The Java Virtual Machine
exits when the only threads running are all daemon threads. This method
must be called before the thread is started.
class adminThread extends Thread {
adminThread() {
setDaemon(false);
}
public void run() {
boolean d = isDaemon();
System.out.println("daemon = " + d);
}
}

public class Tester {


public static void main(String[] args) throws Exception {
Thread thread = new adminThread();
System.out.println("thread = " + thread.currentThread());
thread.setDaemon(false);
thread.start();
}
}
Interrupting threads

A deprecated feature
means it is not in active
development and may be
removed in a future update.
Synchronizing threads
public class Table public class Thread1 extends Thread
{ {
void printTable(int n) // Here, method is not synchronized. Table t; // Declaration of variable t of class type Table.
{
for(int i = 1; i <= 5; i++) // Declare one parameterized constructor and pass variable t as
{ a parameter.
System.out.println(n * i); Thread1(Table t)
try {
{ this.t = t;
Thread.sleep(400); }
} public void run()
catch(InterruptedException ie) {
{ t.printTable(2);
System.out.println(ie); }
} }
}}
}
public class Thread2 extends Thread public class SynchronizedMethod
{ {
Table t; public static void main(String[] args)
Thread2(Table t) {
{ // Create an object of class Table.
this.t = t; Table obj = new Table();
} Thread1 t1 = new Thread1(obj);
public void run() Thread2 t2 = new Thread2(obj);
{ t1.start();
t.printTable(10); t2.start();
} }
} }
public class Table public class Thread1 extends Thread
{ {
synchronized void printTable(int n) // Here, method is Table t; // Declaration of variable t of class type Table.
synchronized.
{ // Declare one parameterized constructor and pass variable t as
for(int i = 1; i <= 5; i++) a parameter.
{ Thread1(Table t)
System.out.println(n * i); {
try this.t = t;
{ }
Thread.sleep(400); public void run()
} {
catch(InterruptedException ie) t.printTable(2);
{ }
System.out.println(ie); }
}
}}
}
public class Thread2 extends Thread public class SynchronizedMethod
{ {
Table t; public static void main(String[] args)
Thread2(Table t) {
{ // Create an object of class Table.
this.t = t; Table obj = new Table();
} Thread1 t1 = new Thread1(obj);
public void run() Thread2 t2 = new Thread2(obj);
{ t1.start();
t.printTable(10); t2.start();
} }
} }
Synchronized Block

public class Table public class Thread1 extends Thread


{ {
Void printable(int n){ Table t; // Declaration of variable t of class type Table.
Synchronized(this) // Here, block is synchronized.
{ // Declare one parameterized constructor and pass variable t as
for(int i = 1; i <= 5; i++) a parameter.
{ Thread1(Table t)
System.out.println(n * i); {
try this.t = t;
{ }
Thread.sleep(400); public void run()
} {
catch(InterruptedException ie) t.printTable(2);
{ }
System.out.println(ie); }
}
}}
}}
public class Thread2 extends Thread public class SynchronizedMethod
{ {
Table t; public static void main(String[] args)
Thread2(Table t) {
{ // Create an object of class Table.
this.t = t; Table obj = new Table();
} Thread1 t1 = new Thread1(obj);
public void run() Thread2 t2 = new Thread2(obj);
{ t1.start();
t.printTable(10); t2.start();
} }
} }
Inter-thread communication
public class ThreadA {

public static void main(String[] args) throws InterruptedException {

ThreadB b = new ThreadB();


b.start();
synchronized (b) {
System.out.println("main thread calling wait() method"); // step 1
b.wait();
System.out.println("main thread got notification call"); // step 4
System.out.println("totol balance " + b.totalBalance);
}

}
class ThreadB extends Thread {

int totalBalance = 0;

public void run() {


synchronized (this) {
System.out.println("child Thread starts calculation for total balance"); // step 2
for (int i = 0; i <= 10; i++) {
totalBalance = totalBalance + i;
}
System.out.println("child thread gives notification call"); // step 3
this.notify();
}
}

You might also like