This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!

primers

Xiao Ming is here again

After xiao Ming changed his career to big data, he deeply felt his own deficiencies, so he decided to carry out intensive learning on his weak projects.

According to Damingti’s big data requirements, Xiao Ming is going to start with what he is familiar with, Java concurrency and JVM.

Xiao Ming has officially started his journey to repair the immortal by big data

“I’ve been waiting and notifying for a long time.

The body of the

To support collaboration between multiple threads, the JDK provides two very important interfaces: the wait() method for threads and the notify() method for notifications.

Why are these two methods not in Thread, but in Object?

On the one hand, this means that any object can call both methods. On the other hand, either the wait() or notify() methods need to get a Monitor for the target object first. If defined in the Thread class, it is inconvenient to obtain the target object’s Monitor; Defined in the Object class, synchronized(this) is required to obtain the Monitor of the current Object.

Why do you need a Monitor?

A Monitor is needed essentially to ensure that only one thread is operating on the same physical region (objects in JVM memory) at a time, and it also ensures efficient communication between different threads.

When the wait() method is called on an object instance, the current thread waits on the object.

What does that mean?

For example, if the obj.wait() method is called in thread A, thread A will stop executing and go into the wait state.

When will the waiting be over?

Thread A waits until another thread calls obj.notify() or obj.notifyAll().

At this point, the object becomes an effective means of communication between multiple threads.

How exactly do the wait() and notify() methods work?

If a thread calls the object.wait() method, it enters the wait set of the object.

There may be more than one thread in the wait queue, because the system is running multiple threads waiting for an object.

When the object.notify() method is called, it randomly selects a thread from the wait queue and wakes it up.

What I want you to notice here is that this selection is not fair. It does not mean that the thread that waits first will be selected first. This selection is completely random.

It is important to note that the object.wait() method cannot be called arbitrarily.

It must be included in the corresponding synchronized statement, and either the wait() or notify() methods must first acquire a monitor for the target object.

The following figure shows the workflow details for the wait() and notify() methods.

T1 and T2 indicate two threads.

T1 must obtain a monitor for the object before the wait() method can be executed correctly.

The wait() method releases the monitor after execution.

The purpose of this is to prevent other threads waiting on the object from failing to execute due to the sleep of T1.

Thread T2 must also get the object’s monitor before the notify() method can be called.

Fortunately, T1 has released the monitor at this point. As a result, T2 can get the object’s monitor without a problem.

T2 then executes the notify() method to try to wake up a waiting thread, assuming T1 is woken up.

The first thing T1 does when it wakes up is not to execute any subsequent code, but to try to retrieve the object’s monitor, which T1 had before the wait() method executed.

If it is not available temporarily, T1 must also wait for the monitor. When the monitor is successfully acquired, T1 can continue in a real sense.

(JDK 1.8.0_192)

Object#wait

/** * Causes the current thread to wait until another thread calls notify() or notifyAll() on this object. * * In other words, this method behaves as if it were simply executing a call to wait(0). * * The current thread must own a monitor for this object. The * * thread releases ownership of this monitor and waits until another thread tells the thread waiting for this object monitor to wake up by calling notify or notifyAll. * * The thread then waits until it can regain ownership of the monitor and resume execution. * * <pre> * synchronized (obj) {* synchronized (obj) {* while (obj) * obj.wait(timeout, nanos); *... // Perform the appropriate operation for the condition *} * </pre> * * This method can only be called by the thread that is the owner of the object monitor. * * See the notify method for a description of how threads become monitor owners. * *@throwsIllegalMonitorStateException if the current thread is not the owner of this object's monitor. *@throwsInterruptedException If any thread interrupts the current thread before or while the current thread is waiting for notification. When this exception is thrown, the interrupt status of the current thread is cleared. * /
public final void wait(a) throws InterruptedException {
    wait(0);
}

/** * Causes the current thread to wait until another thread calls notify() or notifyAll() on this object, or until the specified time has passed. * * The current thread must own a monitor for this object. * * This method causes the current thread (called T) to place itself in the wait set of the object and then discard all synchronization declarations on the object. * * Thread T is disabled for thread scheduling purposes and is dormant until one of the following four conditions occurs: * * 1. Another thread calls the notify method on this object, and thread T happens to be arbitrarily selected as the thread to wake up. * 2. Some other threads call notifyAll on this object. * 3. Other threads interrupt thread T. * 4. The specified real time has passed, more or less. However, if the timeout is 0, timeliness is not considered and the thread simply waits for notification. * * Then remove the thread T from the wait set of the object and re-enable thread scheduling. * * It then competes with other threads for the right to synchronize on the object in the usual way; * * Once it has gained control of the object, all of its synchronization declarations on the object revert to the original state, that is, to the state in which it called the wait method. * * Thread T then returns from the call to wait. * * Therefore, on return from wait, the synchronization state of the object and thread T is exactly the same as it was when wait was called. * * threads can also wake up without notification, interrupt, or timeout, which is called a false wake. * * While this rarely happens in practice, the application must guard against this by testing the condition that should cause the thread to wake up, and wait if the condition is not met. * * <pre> * synchronized (obj) {* synchronized (obj) {* while (obj) * obj.wait(timeout, nanos); *... // Perform the appropriate operation *} * </pre> * * If the current thread is interrupted by any thread before or during the wait, throw InterruptedException. * * This exception will not be thrown until the locked state of the object is restored as described above. * * Notice that the wait method unlocks the object only when it places the current thread in its wait set; Any other objects that can be synchronized with the current thread will remain locked while the thread waits. * * This method can only be called by the thread that is the owner of the object's monitor. * * See the notify method for a description of how threads become monitor owners. * *@paramTimeout Indicates the maximum wait time in milliseconds. *@throwsIllegalArgumentException If the timeout value is negative or the nanos value is not in the range 0 to 999999. *@throwsIllegalMonitorStateException if the current thread is not the owner of this object's monitor. *@throwsInterruptedException If any thread interrupts the current thread before or while the current thread is waiting for notification. When this exception is thrown, the interrupt status of the current thread is cleared. * /
public final native void wait(long timeout) throws InterruptedException;


/** * Causes the current thread to wait until another thread calls notify() or notifyAll() on this object, or until another thread interrupts the current thread, or until a certain actual time has elapsed. * * This method is similar to the one-argument wait method, but it allows better control over the amount of time to wait for notifications before giving up. * * The real time quantity (in nanoseconds) is given by the following formula: 1000000 * timeout + nanos * * In all other respects, this method has the same effect as the one parameter method wait(long). In particular, wait(0,0) has the same meaning as wait(0). * * The current thread must own a monitor for this object. The * * thread releases ownership of this monitor and waits for one of two things to happen: * * 1. Another thread notifies the thread waiting for this object monitor to wake up by calling notify or notifyAll. * 2. The timeout period (specified by the timeout milliseconds and seconds parameter) has expired. * * The thread then waits until it can regain ownership of the monitor and resume execution. * * <pre> * synchronized (obj) {* synchronized (obj) {* while (obj) * obj.wait(timeout, nanos); *... // Perform the appropriate operation for the condition *} * </pre> * * This method can only be called by the thread that is the owner of the object monitor. * * See the notify method for a description of how threads become monitor owners. * *@paramTimeout Indicates the maximum wait time in milliseconds. *@paramNanos additional time, nanosecond range 0-999999. *@throwsIllegalArgumentException If the timeout value is negative or the nanos value is not in the range 0 to 999999. *@throwsIllegalMonitorStateException if the current thread is not the owner of this object's monitor. *@throwsInterruptedException If any thread interrupts the current thread before or while the current thread is waiting for notification. When this exception is thrown, the interrupt status of the current thread is cleared. * /
public final void wait(long timeout, int nanos) throws InterruptedException {
    if (timeout < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
        "nanosecond timeout value out of range");
    }

    if (nanos > 0) {
        timeout++;
    }

    wait(timeout);
}
Copy the code

Object#notify


/** * Wake up the single thread that is waiting for this object monitor. * * If there are any threads waiting for this object, one of them is selected to wake up. * * This choice is arbitrary and at the discretion of the implementation class. The * * thread waits for the object's monitor by calling one of the wait methods. * * The awakened thread cannot continue until the current thread relinquishes its lock on the object. * * Awakened threads will compete in the normal way with any other threads that may actively compete synchronously on this object; For example, there is no advantage or disadvantage to the awakened thread being the next to lock the object. * * This method can only be called by the thread that is the owner of the object's monitor. * * Threads become the owner of an object monitor in one of three ways: * * 1. By executing the synchronized instance methods of the object. * 2. The body of a synchronized statement that is executed on an object. * 3. For objects of class type, execute the synchronous static methods of that class. * * Only one thread at a time can own an object's monitor. * *@throwsIllegalMonitorStateException if the current thread is not the owner of this object's monitor. * /
public final native void notify(a);

/** * Wake up all threads waiting for this object monitor. The * * thread waits for the object's monitor by calling one of the wait methods. * * The awakened thread cannot continue until the current thread relinquishes its lock on the object. * * Awakened threads will compete in the normal way with any other threads that may actively compete synchronously on this object; For example, there is no advantage or disadvantage to the awakened thread being the next to lock the object. * * This method can only be called by the thread that is the owner of the object's monitor. * * See the notify method for a description of how threads become monitor owners. * *@throwsIllegalMonitorStateException if the current thread is not the owner of this object's monitor. * /
public final native void notifyAll(a);
Copy the code