Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
10 views

Module 5 Topic Wize Oops With Java 24-25 (2)

Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Module 5 Topic Wize Oops With Java 24-25 (2)

Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 50

MODULE 5

PREPARED BY
ARPITHA K M
Multithreading in Java
• Multithreading in Java is a powerful programming feature that allows
the execution of multiple threads simultaneously.
• A thread is the smallest unit of a process, and multithreading enables
the concurrent execution of two or more parts of a program to
maximize CPU utilization.
Key Concepts in Multithreading
• Thread: A thread is a lightweight subprocess, a smallest unit of
processing. Each thread in Java runs within a process.
• Main Thread: Every Java program has at least one thread, known as the
main thread. It is created automatically when the program starts.
• Concurrency: It allows multiple threads to run in overlapping time
periods, improving program efficiency.
• Parallelism: True parallel execution of threads on multi-core processors.
The Life Cycle/Model of a Thread in Java
 The Life Cycle of a Thread in Java refers to the state
transformations of a thread that begins with its birth and
ends with its death.
 When a thread instance is generated and executed by calling
the start() method of the Thread class, the thread enters the
runnable state.
 When the sleep() or wait() methods of the Thread class are
called, the thread en
 ters a non-runnable mode.
 Thread returns from non-runnable state to runnable state and
starts statement execution.
 The thread dies when it exits the run() process.
There are basically 4 stages in the lifecycle of a thread, as given below:
New
Runnable
Running
Blocked (Non-runnable state)
Dead
1) New State
• As we use the Thread class to construct a thread entity, the thread
is born and is defined as being in the New state.
• That is, when a thread is created, it enters a new state, but the
start() method on the instance has not yet been invoked.
Ex: Thread t = new Thread();
2) Runnable State
• A thread in the runnable state is prepared to execute the code.
When a new thread's start() function is called, it enters a runnable
state.
• In the runnable environment, the thread is ready for execution and
is awaiting the processor's availability (CPU time).
• That is, the thread has entered the queue (line) of threads waiting
for execution.
EX: t.start();
3) Running State
 Running implies that the processor (CPU) has assigned a time slot to the thread for execution.
 When a thread from the runnable state is chosen for execution by the thread scheduler, it
joins the running state.
 In the running state, the processor allots time to the thread for execution and runs its run
procedure.
 This is the state in which the thread directly executes its operations. Only from the runnable
state will a thread enter the running state.
The thread is executing its run() method.

4) Blocked State
 When the thread is alive, i.e., the thread class object persists, but it cannot be selected for
execution by the scheduler. It is now inactive.
Ex: Thread.sleep();
5)Dead State
 When a thread's run() function ends the execution of sentences, it automatically dies or
enters the dead state.
 That is, when a thread exits the run() process, it is terminated or killed. When the stop()
function is invoked, a thread will also go dead.
Ex: t.join();
1. Extending the Thread Class
When you extend the Thread class, you create a subclass of Thread and override its run() method.
The run() method contains the code that will execute when the thread starts.
class MyThread extends Thread {
public void run() {
// Code executed by the thread
for (int i = 1; i <= 5; i++) {
System.out.println("Thread running: " + i);
try {
Thread.sleep(500); // Pausing for 500 milliseconds
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread(); // Create an instance of the thread
thread.start(); // Start the thread
}
}
2. Implementing the Runnable Interface
• When you implement the Runnable interface, you create a class that implements Runnable and provide the
thread logic inside the run() method.
• Then, you pass an instance of this class to a Thread object.

Class MyRunnable implements Runnable {


public void run() {
// Code executed by the thread
for (int i = 1; i <= 5; i++) {
System.out.println(" thread running: " + i);
try {
Thread.sleep(500); // Pausing for 500 milliseconds
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
public class Main {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable(); // Create a Runnable object
Thread thread = new Thread(myRunnable); // Pass it to a Thread object
thread.start(); // Start the thread
}
}
OUTPUT
Thread running: 1
Thread running: 2
Thread running: 3
Thread running: 4
Thread running: 5
Main thread in Java
 The main thread in Java is the thread that is automatically
created when a Java program starts.
 It is the entry point for the program and is responsible for
executing the main method.
 Every Java program has at least one thread, the main thread.
 Other threads can be created and started from within the
main thread.
 The main thread continues running until the main method
finishes, but the JVM remains active if other threads are still
running.
 Managing the main thread effectively is essential for
coordinating multithreaded programs.
// Define a class that extends Thread
class MyThread extends Thread {
private String threadName;
public MyThread(String name) {
threadName = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " is running: " + i);
try {
Thread.sleep(500); // Sleep for 500 milliseconds
} catch (InterruptedException e) {
System.out.println(threadName + " was interrupted.");
}
}
System.out.println(threadName + " has finished.");
}
}
// Main class
public class MultithreadingExample {
public static void main(String[] args) {
// Create thread objects
MyThread thread1 = new MyThread("Thread 1");
MyThread thread2 = new MyThread("Thread 2");
// Start the threads
thread1.start();
thread2.start();
// Main thread continues to execute
System.out.println("Main thread is running.");
}
}
Main thread is running.
Thread 1 is running: 1
Thread 2 is running: 1
Thread 1 is running: 2
Thread 2 is running: 2
Thread 1 is running: 3
Thread 2 is running: 3
Thread 1 is running: 4
Thread 2 is running: 4
Thread 1 is running: 5
Thread 2 is running: 5
Thread 1 has finished.
Thread 2 has finished.

NOTE :EXAMPLE ALSO APPLYS FOR CREATIONG MULTIPLE THREADS


public class MainThreadExample {
public static void main(String[] args) {
// Get the reference to the current thread (main thread)
Thread mainThread = Thread.currentThread();
// Print details about the main thread
System.out.println("Main Thread Name: " + mainThread.getName());
System.out.println("Main Thread ID: " + mainThread.getId());
System.out.println("Main Thread Priority: " + mainThread.getPriority());
// Set a new name and priority for the main thread
mainThread.setName("PrimaryThread");
mainThread.setPriority(Thread.MAX_PRIORITY);
// Print updated main thread details
System.out.println("Updated Main Thread Name: " + mainThread.getName());
System.out.println("Updated Main Thread Priority: " + mainThread.getPriority());
// Simulate work in the main thread
for (int i = 1; i <= 5; i++) {
System.out.println("Main thread working: " + i);
try {
Thread.sleep(500); // Pause for 500 milliseconds
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
}
System.out.println("Main thread has finished.");
}
}
OUTPUT
Main Thread Name: main
Main Thread ID: 1
Main Thread Priority: 5
Updated Main Thread Name: PrimaryThread
Updated Main Thread Priority: 10
Main thread working: 1
Main thread working: 2
Main thread working: 3
Main thread working: 4
Main thread working: 5
Main thread has finished.
Method Name Description
Begins a new thread and executes the run() method in a separate
start()
thread.
Contains the code to be executed by the thread. It is called internally
run() by the start() method.
sleep(long millis) Pauses the current thread for the specified number of milliseconds.
join() Waits for the specified thread to finish execution before continuing.
Suggests to the thread scheduler that the current thread can pause
yield()
and allow other threads to run.
interrupt() Signals a thread to stop or handle an interruption.
isAlive() Checks if a thread is still running.
getName() Retrieves the name of the thread.
setName(String name) Sets a new name for the thread.
Retrieves the priority of the thread (default is
getPriority() Thread.NORM_PRIORITY).
setPriority(int priority) Sets the priority of the thread (ranges from 1 to 10).
Using isAlive() and join()
class MyThread extends Thread {
private String threadName;
public MyThread(String name) {
threadName = name;
}
@Override
public void run() {
System.out.println(threadName + " started.");
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " is running: " + i);
try {
Thread.sleep(500); // Sleep for 500 ms
} catch (InterruptedException e) {
System.out.println(threadName + " was interrupted.");
}
}
System.out.println(threadName + " has finished.");
}
}
public class SimplifiedIsAliveJoinExample {
public static void main(String[] args) {
// Create and start threads
MyThread thread1 = new MyThread("Thread 1");
MyThread thread2 = new MyThread("Thread 2");
thread1.start();
thread2.start();
try {
// Wait for threads to complete
thread1.join();
thread2.join();
} catch (InterruptedException e) {
System.out.println("Main thread was interrupted.");
}
// Check if threads are alive
System.out.println("Is " + thread1.getName() + " alive? " + thread1.isAlive());
System.out.println("Is " + thread2.getName() + " alive? " + thread2.isAlive());
System.out.println("Main thread has finished.");
}
}
OUTPUT
Thread 1 is running: 1
Thread 2 is running: 1
Thread 1 is running: 2
Thread 2 is running: 2
Thread 1 is running: 3
Thread 2 is running: 3
Thread 1 has finished.
Thread 2 has finished.
Is Thread 1 alive? false
Is Thread 2 alive? false
Main thread has finished.
Thread Priorities in Java Multithreading
 In Java, each thread is assigned a priority that determines the
order in which threads are scheduled for execution.
 Thread priorities are integers ranging from Thread.
 MIN_PRIORITY (1) to Thread.MAX_PRIORITY (10), with the
default being Thread. NORM_PRIORITY (5).
 Higher priority threads are more likely to be executed before
lower-priority threads, though this behavior is not guaranteed
and depends on the thread scheduler of the operating
system.
class PriorityThread extends Thread {
public PriorityThread(String name) {
super(name); // Set thread name
}
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(getName() + " is running with priority " + getPriority());
try {
Thread.sleep(500); // Pause for 500 ms
} catch (InterruptedException e) {
System.out.println(getName() + " was interrupted.");
}
}
System.out.println(getName() + " has finished.");
}
}
public class ThreadPriorityExample {
public static void main(String[] args) {
// Create threads
PriorityThread t1 = new PriorityThread("Thread 1");
PriorityThread t2 = new PriorityThread("Thread 2");
PriorityThread t3 = new PriorityThread("Thread 3");
// Set thread priorities
t1.setPriority(Thread.MIN_PRIORITY); // Priority 1
t2.setPriority(Thread.NORM_PRIORITY); // Priority 5 (default)
t3.setPriority(Thread.MAX_PRIORITY); // Priority 10
// Start threads
t1.start();
t2.start();
t3.start();
}
}
OUTPUT:
Thread 3 is running with priority 10
Thread 3 is running with priority 10
Thread 3 is running with priority 10
Thread 3 has finished.
Thread 2 is running with priority 5
Thread 2 is running with priority 5
Thread 2 is running with priority 5
Thread 2 has finished.
Thread 1 is running with priority 1
Thread 1 is running with priority 1
Thread 1 is running with priority 1
Thread 1 has finished.
Synchronization in Java
 Synchronization in Java is a critical concept in
concurrent programming that ensures multiple
threads can interact with shared resources like
variables, objects, files, etc safely.
 In a nutshell, synchronization prevents race
conditions, where the outcome of operations depends
on the timing of thread execution.
 It is the capability to control the access of multiple
threads to any shared resource.
 Synchronization is a better option where we want to
allow only one thread to access the shared resource.
1)synchronized method
• When a method is declared synchronized, the
thread must acquire the intrinsic lock
(monitor) of the object before executing the
method.
class Counter {
private int count = 0;
synchronized void increment() {
count++;
}
int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) counter.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) counter.increment();
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final count: " + counter.getCount()); // Output: 2000
}
}
2) synchronized block
• Instead of synchronizing an entire method, you can synchronize specific
blocks of code to improve performance by limiting the synchronized scope.
class Counter {
private int count = 0;
void increment() {
synchronized (this) { // Lock only this block
count++;
}
}
int getCount() {
return count;
}
}
3) Static Synchronization:

Locks at the class level, ensuring no thread can execute any static
synchronized method of the class until the lock is released.
class Counter {
private static int count = 0;

synchronized static void increment() {


count++;
}

static int getCount() {


return count;
}
}
Inter-thread communication
• Inter-thread communication in Java refers to the mechanism by which
threads within the same process can communicate and share data.
• Java provides robust support for inter-thread communication through its
synchronized blocks, locks, and methods for signaling and waiting.
• Shared Resource and Synchronization:Threads often share resources like
variables, data structures, or objects. To ensure consistency and avoid
conflicts, access to these shared resources must be synchronized.
• Java provides synchronized blocks and methods to enforce mutual
exclusion and prevent race conditions.
• wait(), notify(), notifyAll():They must be called within a synchronized block
or method. wait(): Causes the current thread to wait until another thread
invokes notify() or notifyAll() on the same object.
• notify(): Wakes up one thread waiting on the object's monitor.
• notifyAll(): Wakes up all threads waiting on the object's monitor.
class SharedResource {
private boolean available = false;
public synchronized void produce() {
while (available) {
try {
wait(); // Wait until the resource is consumed
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Producing...");
available = true;
notify(); // Notify the consumer thread
}
public synchronized void consume() {
while (!available) {
try {
wait(); // Wait until the resource is produced
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Consuming...");
available = false;
notify(); // Notify the producer thread
}
}
public class InterThreadCommunication {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread producer = new Thread(resource::produce);
Thread consumer = new Thread(resource::consume);
produce.start();
consume.start();
}
}

OUTPUT:Producing...
Consuming...
SUSPENDING,RESUMING,AND STOPPING
THREADS
1.Java Thread suspend() method and resume() method
 The suspend() method of thread class puts the thread from
running to waiting state.
 This method is used if you want to stop the thread execution and
start it again when a certain event occurs.
 method allows a thread to temporarily cease execution. The
suspended thread can be resumed using the resume() method.
 Use a shared flag (volatile boolean) and synchronization to
achieve thread suspension and resumption safely.

 Syntax
 public final void suspend()
class SuspendResumeExample implements Runnable {
private volatile boolean suspended = false;
public synchronized void suspendThread() {
suspended = true;
}
public synchronized void resumeThread() {
suspended = false;
notify(); // Notify the thread to resume
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
synchronized (this) {
while (suspended) {
try {
wait(); // Wait until notified to resume
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Thread interrupted.");
}
}
}
System.out.println("Running: " + i);
try {
Thread.sleep(500); // Simulate work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Thread interrupted during sleep.");
}
}
}
}
public class ThreadControlDemo {
public static void main(String[] args) throws InterruptedException {
SuspendResumeExample example = new SuspendResumeExample();
Thread thread = new Thread(example);
thread.start();
Thread.sleep(2000); // Let the thread run for a while
System.out.println("Suspending thread...");
example.suspendThread();
Thread.sleep(2000); // Wait while the thread is suspended
System.out.println("Resuming thread...");
example.resumeThread();
}
}
OUTPUT
Running: 1
Running: 2
Suspending thread...
Resuming thread...
Running: 3
Running: 4
...
2. Stopping a Thread
 Stopping a thread terminates its execution completely.
 The stop() method is deprecated because it can leave shared resources in an inconsistent state.
 Instead, use a shared flag to signal the thread to stop gracefully.

class StopExample implements Runnable {


private volatile boolean running = true;
public void stopThread() {
running = false; // Signal the thread to stop
}
@Override
public void run() {
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(500); // Simulate work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Thread interrupted.");
}
}
System.out.println("Thread stopped.");
}
}
public class StopThreadDemo {
public static void main(String[] args) throws InterruptedException {
StopExample example = new StopExample();
Thread thread = new Thread(example);
thread.start();
Thread.sleep(3000); // Let the thread run for a while
System.out.println("Stopping thread...");
example.stopThread(); // Stop the thread
}
}

Output
Thread is running...
Thread is running...
Thread is running...
Stopping thread...
Thread stopped.
Obtain a thread's state
 In Java, you can obtain a thread's state using the Thread class's getState() method.
This method returns a value from the Thread.State enum, which represents the
different states a thread can be in during its lifecycle.

Thread States
Java defines the following states for a thread:
1) NEW: A thread is in the NEW state after it has been created but before the start()
method has been invoked.
2) RUNNABLE: A thread enters the RUNNABLE state after the start() method has
been called. In this state, the thread is eligible for execution by the Java Virtual
Machine (JVM), but it may not be running at all times because other threads could
be executing. This is the state where a thread is actively running or waiting for a
CPU time slice.
3) BLOCKED: A thread enters the BLOCKED state when it is waiting for a monitor lock
to enter a synchronized block or method. When another thread is holding the
lock, the thread is blocked.
4) WAITING: A thread is in the WAITING state when it is waiting
indefinitely for another thread to perform a particular action. This is
typically the result of calling methods like Thread.sleep(), Object.wait(),
or LockSupport.park().

5) TIMED_WAITING: A thread enters the TIMED_WAITING state when it is


waiting for a specific period. This happens when the thread calls
methods like Thread.sleep(milliseconds) or Object.wait(milliseconds).

6) TERMINATED: A thread is in the TERMINATED state when it has


completed its execution (i.e., the run() method has finished, or the
thread has been interrupted and has caught the InterruptedException).
class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("Thread state inside run(): " + Thread.currentThread().getState());
Thread.sleep(1000); // Sleep for 1 second
System.out.println("Thread state after sleep(): " + Thread.currentThread().getState());
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
}
public class ThreadStateExample {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
// Thread is in NEW state
System.out.println("Thread state before start(): " + thread.getState());
thread.start(); // Thread moves to RUNNABLE state
// Sleep for a short time to allow the thread to start and sleep
Thread.sleep(200);
// Thread might be in RUNNABLE or TIMED_WAITING state
System.out.println("Thread state during execution: " + thread.getState());
thread.join(); // Wait for the thread to finish
// Thread is in TERMINATED state after completion
System.out.println("Thread state after completion: " + thread.getState());
}
}
output
Thread state before start(): NEW
Thread state inside run(): RUNNABLE
Thread state during execution: TIMED_WAITING
Thread state after sleep(): RUNNABLE
Thread state after completion: TERMINATED
Enumerations
In Java, enumerations (or enums) are a special type of class that
represents a fixed set of constants.
Each constant in an enum is implicitly a public static final variable.
Enums are used to represent a fixed set of related values like days of
the week, months of the year, colors, and so on.

Basic Syntax of Enums


enum EnumName {
CONSTANT_1,
CONSTANT_2,
CONSTANT_3;
}
Fundamentals of enum
1. Definition
 Enumerations are created using the enum keyword.
 Constants within the enumeration are called enumeration constants.
2. Enum Constants
 Enum constants are defined as identifiers in the enum declaration and are implicitly
public static final.
 This means they are constants that cannot be changed.
Example:
enum Color {
RED, GREEN, BLUE;
}

3. Enum Fields, Methods, and Constructors


You can add fields, methods, and even constructors to an enum. Each enum constant can
have different values or behaviors depending on how you define them.
enum Day {
MONDAY("Weekday"),
TUESDAY("Weekday"),
WEDNESDAY("Weekday"),
THURSDAY("Weekday"),
FRIDAY("Weekday"),
SATURDAY("Weekend"),
SUNDAY("Weekend");
private final String type; // Instance field
// Constructor to set the type
Day(String type) {
this.type = type;
}
// Method to get the type
public String getType() {
return type;
}
}
4. Enum Methods
Enums have several useful methods, including:
 values(): Returns an array containing all the constants
in the enum.
 valueOf(String name): Returns the enum constant with
the specified name. Throws an
IllegalArgumentException if the name does not match
any constant.
 ordinal(): Returns the index of the enum constant (its
position in the enum declaration, starting from 0).
 toString(): Returns the name of the constant.
public class EnumExample {
public static void main(String[] args) {
// Using values()
for (Day day : Day.values()) {
System.out.println(day + " is a " + day.getType());
}
// Using valueOf()
Day today = Day.valueOf("MONDAY");
System.out.println("Today is: " + today);
// Using ordinal()
System.out.println("Ordinal of SUNDAY: " + Day.SUNDAY.ordinal());
}
}

Output
MONDAY is a Weekday
TUESDAY is a Weekday
WEDNESDAY is a Weekday
THURSDAY is a Weekday
FRIDAY is a Weekday
SATURDAY is a Weekend
SUNDAY is a Weekend
Today is: MONDAY
Ordinal of SUNDAY: 6
5.Instantiation:Enumerations define a class type, but they are not
instantiated using the new keyword.
Enumeration variables are declared and used similarly to primitive
types.
6.Assignment and Comparison:
Enumeration variables can only hold values defined by the
enumeration.
Constants can be assigned to enumeration variables using the dot
notation( EnumType.Constant)
Constants can be compared for equality using the == operator
7.Switch Statements:Enumeration values can be used to control switch
statements.
All case statements within the switch must use constants from the
same enum as the switch expression.
Constants in case statements are referenced without qualification by
their enumeration type name.
values() and valueOf() methods
 In Java, both the values() and valueOf() methods are built-in
methods available to all enum types.
 These methods are automatically provided by the Java compiler
when you define an enum type.

1. values() Method
• The values() method is implicitly provided by Java for all enums.
This method returns an array of all the constants of the enum
type in the order they are declared.

• Purpose: To get an array containing all the enum constants.


• Return type: An array of the enum type (i.e., EnumType[]).
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
public class EnumExample {
public static void main(String[] args) {
// Using the values() method to get all enum constants
Day[] days = Day.values();
// Looping through the array and printing each day
for (Day day : days) {
System.out.println(day);
}
}
}

OUTPUT: MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
2. valueOf(String name) Method
 The valueOf() method is another built-in
method that is used to convert a String to its
corresponding enum constant.

 Purpose: To get the enum constant


corresponding to a specific String.
 Parameters: The name of the constant (case-
sensitive).
 Return type: The enum constant corresponding
to the given string.
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
public class EnumExample {
public static void main(String[] args) {
// Using valueOf() to convert string to enum constant
String inputDay = "MONDAY";
Day day = Day.valueOf(inputDay); // Converts the string to the corresponding enum constant
System.out.println("Day is: " + day); // Output: Day is: MONDAY
// Example with invalid input (throws IllegalArgumentException)
try {
Day invalidDay = Day.valueOf("FUNDAY"); // This will throw an exception
} catch (IllegalArgumentException e) {
System.out.println("Invalid day: " + e.getMessage()); // Output: Invalid day: No enum constant
Day.FUNDAY
}
}
}

OUTPUT:
Day is: MONDAY
Invalid day: No enum constant Day.FUNDAY

You might also like