Multithreading 2.3.2
Multithreading 2.3.2
2
Thread Priorities in Java
• 1. Thread Priorities in Java
• Thread priority refers to the relative importance of a thread in
relation to others, determining how the operating system schedules
threads for execution. In Java, thread priorities allow the
programmer to influence the order in which threads are executed.
3
• Thread.MIN_PRIORITY = 1
• Thread.NORM_PRIORITY = 5 (default)
• Thread.MAX_PRIORITY = 10
• While the Java Virtual Machine (JVM) allows you to set thread
priorities, the actual impact on scheduling depends on the underlying
operating system's thread scheduling policy. Most operating systems
do not strictly follow the priority values set by Java but use them as
hints for thread scheduling.
4
Setting Thread Priorities
To set a thread's priority, you can use the setPriority(int priority) method of the Thread class. Here’s an example of how
to set a thread’s priority:
java
Thread thread1 = new Thread(() -> {
System.out.println("Thread 1 is running");
});
Thread thread2 = new Thread(() -> {
System.out.println("Thread 2 is running");
});
thread1.start();
thread2.start();
5
Synchronization
Synchronization in Java is a mechanism used to control access to shared resources by multiple threads, ensuring that only one
thread can access a resource at a time. This prevents race conditions, where multiple threads concurrently modify the same
data, leading to unpredictable and incorrect results.
6
2.2 Synchronizing Methods
To ensure thread safety, Java provides the synchronized keyword, which can be applied to methods to ensure
that only one thread can execute that method at a time.
java
public synchronized void increment() {
count++;
}
When a method is declared synchronized, a lock is acquired on the object that the method belongs to (in this
case, the instance of the Counter class). This prevents other threads from accessing any synchronized method
on the same object until the lock is released.
7
Synchronizing Blocks
2.3 Synchronizing Blocks
You can also synchronize specific blocks of code within a method. This is useful when you
want to limit the scope of synchronization to a smaller portion of the method. Here’s an
example:
java
public void increment() {
synchronized(this) {
count++;
}
}
In this case, the synchronized block ensures that only one thread can increment the counter at a
time, but it does not block other parts of the method from being executed concurrently.
8
Deadlock
A common problem with synchronization is deadlock, which occurs when two or more threads are blocked indefinitely,
each waiting for the other to release a lock. Consider the following example:
java
public class Deadlock {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
synchronized (lock2) {
// Do something
}
}
}
public void method2() {
synchronized (lock2) {
synchronized (lock1) {
// Do something
}}}}
9
Inter-thread Communication
3. Inter-thread Communication in Java
Inter-thread communication refers to the ability of threads to communicate with each other, typically to
coordinate their execution or exchange data. Java provides a powerful set of tools for inter-thread
communication, primarily through the wait(), notify(), and notifyAll() methods, which are part of the
Object class.
wait(): Causes the current thread to release the lock and enter the waiting state until another thread
sends a notification.
notify(): Wakes up a single thread that is waiting on the object’s monitor.
notifyAll(): Wakes up all threads waiting on the object’s monitor.
10
Here’s an example demonstrating how these methods can be used for inter-thread communication:
java
class ProducerConsumer {
private static final int MAX_CAPACITY = 10;
private final List<Integer> buffer = new ArrayList<>();
11
public synchronized void consume() throws InterruptedException {
while (buffer.isEmpty()) {
wait(); // Wait until there's something to consume
}
int item = buffer.remove(0);
System.out.println("Consumed: " + item);
notify(); // Notify producer that space is available
}
}
12
public class ProducerConsumerTest {
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
// Producer thread
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
pc.produce(i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
13
// Consumer thread
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
pc.consume();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
In this example:
The producer adds items to the buffer. If the buffer is full, it waits.
The consumer removes items from the buffer. If the buffer is empty, it waits.
The notify() method ensures that the producer and consumer are not blocking each other indefinitely.
14
// Consumer thread
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
pc.consume();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
In this example:
The producer adds items to the buffer. If the buffer is full, it waits.
The consumer removes items from the buffer. If the buffer is empty, it waits.
The notify() method ensures that the producer and consumer are not blocking each other indefinitely.
15
THANK YOU
16