1. Introduction
In Java concurrent programming, realizing collaboration and synchronization between threads is an extremely critical task. In addition to usingObject
Classicwait()
、notify()
andnotifyAll()
Methods implement simple waiting - In addition to the notification mechanism, Java also providesCondition
interface, it withReentrantLock
Used in conjunction, it can achieve more flexible and finer inter-thread communication. This article will explore in depthCondition
The interface and the waiting notification mechanism behind it.
2. Condition interface overview
2.1 Basic Concept
Condition
The interface is located atIn the package, it provides similar
Object
Classicwait()
、notify()
andnotifyAll()
The function of the method, butCondition
More powerful and flexible.Condition
The example is throughLock
The object'snewCondition()
Methods created, eachLock
Objects can create multipleCondition
Instance, this allows us to wait and wake up threads for different conditions.
2.2 Differences between the Object class waiting for notification methods
-
Different associated objects:
Object
Classicwait()
、notify()
andnotifyAll()
The method must be insynchronized
Used in blocks or methods, they are associated with the internal lock of the object; andCondition
Interface methods (such asawait()
、signal()
andsignalAll()
) Must be withLock
The object is used in conjunction withLock
Object. -
Different flexibility:
Condition
Multiple waiting queues can be created, allowing finer granular thread control. For example, one thread can wait for a specific condition, while another thread can wake up the thread waiting for that condition, andObject
The waiting notification method of the class can only operate an implicit waiting queue.
3. Common methods of Condition interface
3.1 await () method
await()
The method will cause the current thread to enter a waiting state until other threads call theCondition
ofsignal()
orsignalAll()
Method, or the current thread is interrupted. Callawait()
When the method is used, the current thread will release the heldLock
, after being awakened, theLock
. The sample code is as follows:
import ; import ; import ; public class AwaitExample { private final Lock lock = new ReentrantLock(); private final Condition condition = (); public void awaitMethod() { (); try { ("Thread " + ().getName() + " is waiting."); (); ("Thread " + ().getName() + " is awakened."); } catch (InterruptedException e) { ().interrupt(); } finally { (); } } }
3.2 signal () method
signal()
The method will wake up in thisCondition
on a single thread waiting. If multiple threads are waiting, only one of the threads will be awakened. It is uncertain which thread will be awakened. The sample code is as follows:
import ; import ; import ; public class SignalExample { private final Lock lock = new ReentrantLock(); private final Condition condition = (); public void signalMethod() { (); try { ("Thread " + ().getName() + " is signaling."); (); } finally { (); } } }
3.3 signalAll () method
signalAll()
The method will wake up in thisCondition
All threads waiting on. The awakened thread will compete to obtainLock
, getLock
The thread will continue to execute. The sample code is as follows:
import ; import ; import ; public class SignalAllExample { private final Lock lock = new ReentrantLock(); private final Condition condition = (); public void signalAllMethod() { (); try { ("Thread " + ().getName() + " is signaling all."); (); } finally { (); } } }
4. Application scenarios of the Condition interface
4.1 Producer-Consumer Model
useCondition
Interfaces can implement more complex producer-consumer models. For example, when the buffer is full, the producer thread waits; when the buffer is empty, the consumer thread waits. The sample code is as follows:
import ; import ; import ; import ; class Buffer { private final LinkedList<Integer> buffer = new LinkedList<>(); private static final int MAX_SIZE = 5; private final Lock lock = new ReentrantLock(); private final Condition notFull = (); private final Condition notEmpty = (); public void produce(int item) { (); try { while (() == MAX_SIZE) { ("Buffer is full, producer is waiting."); (); } (item); ("Produced: " + item); (); } catch (InterruptedException e) { ().interrupt(); } finally { (); } } public int consume() { (); try { while (() == 0) { ("Buffer is empty, consumer is waiting."); (); } int item = (); ("Consumed: " + item); (); return item; } catch (InterruptedException e) { ().interrupt(); return -1; } finally { (); } } } public class ProducerConsumerWithCondition { public static void main(String[] args) { Buffer buffer = new Buffer(); Thread producer = new Thread(() -> { for (int i = 0; i < 10; i++) { (i); } }); Thread consumer = new Thread(() -> { for (int i = 0; i < 10; i++) { (); } }); (); (); } }
4.2 Multi-threaded task coordination
In some multithreaded tasks, the execution order of threads needs to be coordinated according to different conditions. For example, a thread needs to wait for several other threads to complete a specific task before continuing to execute, and you can useCondition
Implemented by interface.
5. Implementation principle of Condition interface
Condition
The implementation of interfaces usually depends onAbstractQueuedSynchronizer
(AQS). EachCondition
The instance has a waiting queue associated with it, when the thread calls itawait()
When the method is used, the thread will be encapsulated into a node and added to the waiting queue, and the held thread will be released.Lock
. When other threads callsignal()
orsignalAll()
When a method is used, the corresponding node will be removed from the waiting queue and added to theLock
in the synchronization queue, waiting to be retrievedLock
。
6. Things to note when using the Condition interface
6.1 Acquisition and release of locks
In callingCondition
Before the interface method, the associated one must be obtained first.Lock
, and make sure to release it after useLock
, usually usedtry - finally
Block to ensure this.
6.2 Interrupt processing
await()
The method will be thrownInterruptedException
Exception, so appropriate exception handling is required in the code to ensure that the thread can respond correctly when it is interrupted.
6.3 Conditional judgment
In callingawait()
When using the method, you usually need to use itwhile
Cycle to make conditional judgments, notif
Sentence. This is because in a multi-threaded environment, a false wake-up may occur after the thread is awakened.while
The loop can ensure that the conditions are still met.
7. Summary
Condition
The interface provides a powerful and flexible inter-thread waiting notification mechanism for Java concurrent programming. ByReentrantLock
Used in conjunction, more complex and finer thread synchronization and collaboration can be achieved. In actual development, use it reasonably according to specific business needs.Condition
Interfaces can improve the concurrency performance and reliability of programs. At the same time, it is necessary to pay attention to problems such as acquisition and release of locks, interrupt processing, and conditional judgment to avoid concurrency problems.
This is the end of this article about exploring Java's Condition interface and waiting notification mechanism. For more related Java condition waiting notification mechanism content, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!