Wait (), notify(), and notifyAll()

If synchronized is used to ensure thread safety, wait(), notify(), and notifyAll() can be used to realize thread communication. None of these methods are declared in the Thread class, but in the Object class. The reason is that every object has a lock, so having the current thread wait for the lock on an object, of course, should be done through that object. And because the current thread may be waiting for locks from multiple threads, doing so through threads can be complicated. In addition, all three methods are native and final and cannot be overridden.

The wait() method causes the current thread to release the object lock and block. The notify() method is used to wake up a thread that is waiting for the corresponding object lock and put it into the ready queue so that it can compete for the lock after the current thread releases the lock and get the CPU execution. NotifyAll () is used to wake up all threads waiting for the corresponding object lock and put them into the ready queue, so that they can compete for the lock after the current thread releases the lock, and thus get CPU execution.

Each lock object has two queues, a ready queue and a blocking queue. The ready queue stores the threads that are ready (to compete for locks), and the blocking queue stores the threads that are blocked. When a blocked thread is woken up, it enters the ready queue and waits for the CPU to dispatch it. Conversely, when a thread is waited, it enters a blocking queue and waits to be woken up.

Await (), signal(), signalAll()

If locks are used between threads to keep them thread-safe, we can use await(), signal(), signalAll() to communicate with threads. All three of these methods are in the Condition interface, which emerged in Java 1.5 as an alternative to the traditional Wait + Notify approach for collaboration between threads and relies on Lock. Compared to wait+notify, using await+signal in Condition is a safer and more efficient way to achieve collaboration between threads.

Condition depends on the Lock interface, and the basic code for generating a Condition is lock.newcondition (). It is important to note that Condition await()/signal()/signalAll() must be used within lock protection, that is, between lock.lock() and lock.unlock. In fact, await()/signal()/signalAll() has a natural correspondence with wait()/notify()/notifyAll(). That is, await() in Conditon corresponds to wait() of Object, signal() in Condition corresponds to notify() of Object, and signalAll() in Condition corresponds to notifyAll() of Object.

BlockingQueue

Java 5 provides a BlockingQueue interface. Although BlockingQueue is also a subinterface of Queue, its primary use is not as a container, but as a tool for thread communication. BlockingQueue has a characteristic: When a producer thread tries to put an element into the BlockingQueue, if the queue is full, the thread will block. When the consumer thread tries to fetch an element from BlockingQueue, it blocks if the queue is empty.

The two threads of the program can control thread communication by alternately putting and taking elements out of the BlockingQueue. Threads need to communicate, and the classic scenario is the producer-consumer model, for which BlockingQueue provides a solution.