0% found this document useful (0 votes)
28 views18 pages

Multithreading in Java

Uploaded by

amogh.patadi
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)
28 views18 pages

Multithreading in Java

Uploaded by

amogh.patadi
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/ 18

MULTITHREADING IN JAVA

● A thread is a lightweight process that can run concurrently with other threads.
● It is the smallest unit of a program that can be executed independently.

Creating Threads in Java

There are two main ways to create a thread in Java:

1. By extending the Thread class


2. By implementing the Runnable interface

Extending the Thread Class


The Thread class is defined in the java.lang package, and it encapsulates a thread of
execution. The Thread class provides various methods to manage and control threads,
such as start(), run(), sleep(), join(), interrupt(), and many others.

Example Program:
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running...");
}

public static void main(String[] args) {


MyThread t1 = new MyThread();
t1.start(); // This will call the run method in a new thread
}
}

Implementing the Runnable Interface


When you implement the Runnable interface, you create a class that implements the run
method. This approach is more flexible because your class can extend another class if
needed.
Example Program:

class MyRunnable implements Runnable {


public void run() {
System.out.println("Thread is running...");
}

public static void main(String[] args) {


MyRunnable myRunnable = new MyRunnable();
Thread t1 = new Thread(myRunnable);
t1.start(); // This will call the run method in a new thread
}
}

Thread Life Cycle

The life cycle of a thread in Java includes the following states:

1. New: The thread is created but not yet started.


2. Runnable: The thread is ready to run and waiting for CPU time.
3. Running: The thread is currently executing.
4. Blocked: The thread is blocked and waiting for a monitor lock.
5. Waiting: The thread is waiting indefinitely for another thread to perform a
particular action.
6. Timed Waiting: The thread is waiting for another thread to perform a specific
action within a specified waiting time.
7. Terminated: The thread has finished its execution.

Example Program for Thread Life Cycle:

class MyThread extends Thread {

public void run() {

try {

System.out.println("Thread is running...");
Thread.sleep(1000); // Timed Waiting state

System.out.println("Thread is awake and running again...");

} catch (InterruptedException e) {

System.out.println("Thread interrupted.");

public static void main(String[] args) {

MyThread t1 = new MyThread();

System.out.println("Thread state: " + t1.getState()); // New

t1.start();

System.out.println("Thread state: " + t1.getState()); // Runnable

try {

Thread.sleep(500);

System.out.println("Thread state: " + t1.getState()); // Timed Waiting

t1.join();

System.out.println("Thread state: " + t1.getState()); // Terminated

} catch (InterruptedException e) {

e.printStackTrace();

}
Key Methods in Thread Class

● start(): Starts the execution of the thread.


● run(): Contains the code that defines the behavior of the thread.
● join(): Waits for the thread to die.
● sleep(long millis): Causes the thread to suspend execution for a
specified period.
● interrupt(): Interrupts the thread.
● setPriority(int priority): Sets the priority of the thread.
● getPriority(): Returns the priority of the thread.
● getState(): Returns the state of the thread.

Main Thread

Every application has at least one thread, known as the main thread. When a Java
program starts, the Java Virtual Machine (JVM) creates this main thread, which is
responsible for the execution of the main method. From this main thread, additional
threads can be spawned to perform parallel processing.

The main thread is important for several reasons:

● It is the entry point for any standalone application.


● It manages the lifecycle of other threads created within the application.
● It is typically the last thread to finish, ensuring that all other threads complete
their execution before the application terminates.

Example Program for Main Thread:

class MainThreadExample {

public static void main(String[] args) {

// Displaying information about the main thread

Thread mainThread = Thread.currentThread();


System.out.println("Main thread name: " + mainThread.getName());

// Creating and starting additional threads

Thread t1 = new Thread(new MyRunnable(), "Thread-1");

Thread t2 = new Thread(new MyRunnable(), "Thread-2");

t1.start();

t2.start();

try {

// Main thread waits for t1 and t2 to finish

t1.join();

t2.join();

} catch (InterruptedException e) {

System.out.println("Main thread interrupted.");

System.out.println("Main thread execution complete.");

class MyRunnable implements Runnable {

public void run() {

System.out.println(Thread.currentThread().getName() + " is running.");

try {

Thread.sleep(500); // Simulating work by sleeping


} catch (InterruptedException e) {

System.out.println(Thread.currentThread().getName() + " interrupted.");

System.out.println(Thread.currentThread().getName() + " finished execution.");

Explanation

1. Main Thread Information:


○ The main thread retrieves and displays its name using
Thread.currentThread().getName().
2. Creating Additional Threads:
○ Two additional threads (t1 and t2) are created using the Thread
class constructor that takes a Runnable object and a thread name.
○ The MyRunnable class implements the Runnable interface and
defines the run() method that the threads will execute.
3. Starting Additional Threads:
○ The start() method is called on both t1 and t2, which begins their
execution by invoking their run() methods.
4. Main Thread Waiting:
○ The main thread uses the join() method to wait for both t1 and t2
to finish their execution. This ensures that the main thread does not
terminate before the additional threads complete.
5. Completion:
○ After t1 and t2 complete their execution, the main thread prints a
message indicating that its execution is complete.
NOTE:

The main thread and normal threads (also known as user-defined threads) have
some key differences.

Main Thread

1. Creation:
○ Automatically created by the JVM when the program starts.
○ Executes the main method of the class.
2. Entry Point:
○ The starting point of any Java application.
○ Responsible for the initial setup and starting other threads if necessary.
3. Lifecycle:
○ Starts when the program begins.
○ Usually the last thread to complete, ensuring all user-defined threads
have finished their execution before the program terminates.
4. Control:
○ Can create, start, and control the lifecycle of other threads.
○ Often acts as a coordinator, managing other threads and resources.
5. Termination:
○ The JVM waits for the main thread to complete before terminating the
program, provided all other non-daemon threads have finished.

Normal Thread (User-Defined Thread)

1. Creation:
○ Created explicitly by the programmer using the Thread class or by
implementing the Runnable interface.
○ Can be started from the main thread or from other user-defined
threads.
2. Entry Point:
○ The starting point is defined by the run method of the Thread class or
Runnable interface.
3. Lifecycle:
○ Starts when the start method is called.
○ Independently runs and completes its task.
○ Its lifecycle is managed by the thread that created it or by the
programmer.
4. Control:
○ Can be controlled and coordinated by other threads, including the main
thread.
○ Can perform various tasks concurrently with other threads.
5. Termination:
○ Can terminate when its run method completes, when it is interrupted,
or when it explicitly calls methods to stop itself.

Creating and Running Multiple Threads

Step-by-Step Code

1. Define a Thread Class: Extend the Thread class and override the run
method.
2. Create and Start Threads: In the main method, create instances of the thread
class and start them.

Example program for Multi_Threads:


// Define a Thread class by extending the Thread class

class MyThread extends Thread {

private String threadName;

MyThread(String threadName) {

this.threadName = threadName;

@Override

public void run() {

for (int i = 0; i < 5; i++) {

System.out.println(threadName + " is running: " + i);

try {

Thread.sleep(500); // Sleep for 0.5 seconds

} catch (InterruptedException e) {

System.out.println(threadName + " was interrupted.");

System.out.println(threadName + " has finished execution.");

}
// Main class to run the threads

public class MultiThreadExample {

public static void main(String[] args) {

// Create instances of MyThread

MyThread thread1 = new MyThread("Thread 1");

MyThread thread2 = new MyThread("Thread 2");

// Start the threads

thread1.start();

thread2.start();

Explanation

1. MyThread Class:
○ This class extends the Thread class.
○ It has a constructor to set the thread name.
○ The run method contains a loop that prints the thread name and
iteration number, then sleeps for 0.5 seconds.
2. Main Method:
○ In the main method, we create two instances of the MyThread class,
each with a different name.
○ We start both threads using the start method, which internally calls
the run method.
Thread priorities:

They are used to hint the thread scheduler about the relative importance of threads.
The scheduler uses these priorities to decide when each thread should run. Here
,each thread is assigned a priority, which is an integer value between
Thread.MIN_PRIORITY (1) and Thread.MAX_PRIORITY (10). By default, a
thread is given a priority of Thread.NORM_PRIORITY (5).

Key Points about Thread Priorities

1. Range of Priorities:
○ Thread.MIN_PRIORITY = 1
○ Thread.NORM_PRIORITY = 5
○ Thread.MAX_PRIORITY = 10
2. Setting Thread Priorities:
○ You can set a thread's priority using the setPriority(int
priority) method.
○ You can get a thread's priority using the getPriority() method.
3. Priority Inheritance:
○ When a new thread is created, it inherits the priority of the thread that
created it.
4. Scheduler Behavior:
○ The behavior of thread scheduling is platform-dependent. On some
platforms, higher-priority threads may run more frequently than
lower-priority threads.
○ Java does not guarantee the exact behavior of thread priorities. It is up
to the JVM implementation and the underlying operating system.
Example Programs :

// Define a Thread class by extending the Thread class

class MyThread extends Thread {

private String threadName;

MyThread(String threadName) {

this.threadName = threadName;

@Override

public void run() {

for (int i = 0; i < 5; i++) {

System.out.println(threadName + " is running: " + i + " with priority: " +


getPriority());

try {

Thread.sleep(500); // Sleep for 0.5 seconds

} catch (InterruptedException e) {

System.out.println(threadName + " was interrupted.");

System.out.println(threadName + " has finished execution.");

}
// Main class to run the threads

public class ThreadPriorityExample {

public static void main(String[] args) {

// Create instances of MyThread

MyThread thread1 = new MyThread("Thread 1");

MyThread thread2 = new MyThread("Thread 2");

MyThread thread3 = new MyThread("Thread 3");

// Set thread priorities

thread1.setPriority(Thread.MIN_PRIORITY); // Priority 1

thread2.setPriority(Thread.NORM_PRIORITY); // Priority 5

thread3.setPriority(Thread.MAX_PRIORITY); // Priority 10

// Start the threads

thread1.start();

thread2.start();

thread3.start();

}
Synchronization In Thread

Synchronization in Java is a mechanism that is used to control the access of multiple


threads to shared resources. It is crucial in preventing thread interference and
ensuring data consistency when multiple threads try to modify the same resource
concurrently.

Key Concepts of Synchronization

Synchronized Methods:

● You can use the synchronized keyword to ensure that only one thread can
execute a method at a time.

Example:
public synchronized void synchronizedMethod() {
// code to be synchronized
}

Synchronized Blocks:

● You can use synchronized blocks to lock a specific object instead of locking
the whole method.

Example:
public void method() {
synchronized(this) {
// code to be synchronized
}
}
Intrinsic Locks (or Monitors):

● Every object in Java has an intrinsic lock. A thread automatically acquires the
intrinsic lock when it enters a synchronized method or block, and releases it
when it exits.
Static Synchronization:

● To synchronize static methods, use the class object for synchronization.

public static synchronized void staticSynchronizedMethod() {


// code to be synchronized
}

Example Program :
// Shared Resource
class Counter {
private int count = 0;

// Synchronized method to ensure thread safety


public synchronized void increment() {
count++;
}

public int getCount() {


return count;
}
}

// Thread class that increments the counter


class CounterThread extends Thread {
private Counter counter;

CounterThread(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
}

// Main class to run the threads


public class SynchronizationExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Creating multiple threads
CounterThread thread1 = new CounterThread(counter);
CounterThread thread2 = new CounterThread(counter);
// Starting the threads
thread1.start();
thread2.start();
try {
// Wait for threads to finish
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Printing the final count
System.out.println("Final count: " + counter.getCount());
}
}

Explanation :
Counter Class:

● This class contains a shared resource count.


● The increment method is synchronized to ensure that only one thread can
modify the count at a time.

CounterThread Class:
● This class extends the Thread class and increments the counter 1000 times
in the run method.

SynchronizationExample Class:

● In the main method, we create an instance of the Counter class.


● We then create and start two threads (thread1 and thread2), both of which
share the same Counter instance.
● We use the join method to wait for both threads to finish.
● Finally, we print the final value of the count variable.

Inter-thread communication in threads

Inter-thread communication in Java is essential for allowing threads to communicate


with each other.

This is typically achieved using the wait(), notify(), and notifyAll()


methods, which are part of the Object class.

Key Concepts

1. wait():
○ Causes the current thread to wait until another thread invokes
notify() or notifyAll() on the same object.
○ The current thread must own the object's monitor to call this method
(i.e., it must be in a synchronized block/method).
2. notify():
○ Wakes up a single thread that is waiting on the object's monitor. If
multiple threads are waiting, one is chosen arbitrarily.
○ The current thread must own the object's monitor to call this method.
3. notifyAll():
● Wakes up all threads that are waiting on the object's monitor.
● The current thread must own the object's monitor to call this method.
Suspending Threads

Deprecated Method: suspend()

● The suspend() method was used to pause the execution of a thread.


● It is deprecated because it can cause deadlocks if the thread holding a lock is
suspended.

Resuming Threads

Deprecated Method: resume()

● The resume() method was used to resume a thread that had been
suspended.
● It is deprecated because it can cause deadlocks and other synchronization
issues.

Modern Approach: As shown in the example above, use a flag to control when the
thread should resume.

Stopping Threads

Deprecated Method: stop()

● The stop() method was used to terminate a thread.


● It is deprecated because it can leave shared resources in an inconsistent
state and can cause deadlocks.

You might also like