Java Concurrency (JUC) --- notify (), notifyAll () and wait () (standard paradigm of waiting and notification)

Standard paradigm of waiting and notification

** a waiting notification and commonly used methods:

1) wait () threads wait (blocking) (method on the Object)
the Notify / notifyAll thread notification (wake-up)

2) the difference between notify () and notifyAll () :( a quick look)
(Simple version understanding)
1.notify (): denotes a random wake a thread (internal scheduling by the operating system), this process can cause loss of signal case (illustrated by the following specific examples)
2.notifyAll (): wake up all threads represent, will not cause loss of signal (so use the time recommended to make use notifyAll)

(Understanding complex version) (skip)
will speak about two concepts:

  • Lock pool: Suppose A thread already has an object (note: not the class) lock, while the other thread wants to call a synchronized method of this object (or synchronized block), since these threads in synchronized way into objects before you must first obtain ownership of the lock of the object, but the object's lock is currently owned by the thread a, so the thread enters the lock pool the object.

  • Wait pool: Suppose a thread A calls an object's wait () method, thread A releases the lock of the object (because the wait () method must appear in synchronized, so natural in execution wait () method before thread A it already has a lock of the object), while thread a enters into the wait pool object. If another thread calls the same object notifyAll () method, the thread pool to wait in the object's lock will all enter the pool of the object, ready to compete for ownership of the lock. If another thread calls the same object notify () method, then there is only one thread in a wait pool of the object (random) will enter the object's lock pool.

    Then again, it's the difference between notify and notifyAll
    if the calling thread object's wait () method, the thread will be the object in a wait pool, pool thread will not wait for the competition to lock the object.
    When there is a thread calls the object notifyAll () method (wake up all wait thread) or notify () method (random only wake a wait thread), wakes up the thread goes to lock the pool of the object, lock the pool thread lock to compete for the object. In other words, as long as the call to notify a thread into the lock by the pool waiting for the pool, while the object notifyAll will move all the threads waiting pool to lock the pool, waiting for the lock to compete

    High priority threads competing to lock the probability of large objects, if a thread is no competition to the object lock, it will stay in the lock pool, the only thread calls again wait () method, it will return to the waiting pool in. The competition subject to lock down the thread execution continues until the execution is over synchronized block of code, it will free up the object lock, then lock the thread pool will continue to compete the object lock.

**

II. Standard paradigm and wait for notification ( focus )

*
1) Wait side: a lock of the object acquired.
B judges whether the cycle is not satisfied with a wait () method.
C execute business logic conditions are met.

2) Notify Party:. A lock of the object acquired
. B change condition
c notify all objects waiting thread waiting pool.

Said foggy as direct business with a simple example of the above paradigm is described step by step

Examples of business: There is now a courier instance Express, which contains two basic attributes km (represented mileage Express) and site (delivery destination), we express is that this business needs in the transport process as long as it is transported not exceed a certain number of miles far cry, it's still on the road (represented blocking); and delivery destination is the same reason, as long as it does not reach a specific place, it says on the road (represented blocking) us. need to do is wait for more than a far cry or reach a certain place, we will continue to implement its own business logic (the equivalent of a courier arrives at another site, reassigned to a new site)

Analysis: It is clear that the above is in line with our business logic waiting notification paradigm, express delivery to the destination party not to reach a certain mileage or time will be in a wait state, it is waiting for the party to notify its wake. (Explained below in code)
Note: Only when our more than 100 kilometers or destination is Beijing, we considered a complete transportation

Code implementation:
1. Define a simple delivery entity class (constructors and properties)

   //初始目的地
    public final static String CITY="ShangHai";
    //快递的里程数
    private int km;
    //快递的目的地
    private String site;

    public Express() {
    }

    public Express(int km, String site) {
        this.km = km;
        this.site = site;
    }

2. The method defined two notification method
explained: notifying parties: a lock of the object acquired (plus synchronized keyword in the method, retrieves a lock on the object).
B change condition (km or change the value of the site. let wait represent parties reach a certain condition, that is, let the party waiting to be awakened)
c. inform all objects waiting in the waiting pool of threads (notifyAll notification indicating that all threads in the waiting)

 /**
     * 变化公里数,然后通知处于wait状态,并需要处理公里
     * 数的线程进行业务处理(通知方)
     */
    public synchronized void changeKm(){
        this.km=101;
        notifyAll();

    }

    /**
     * 变化地点,然后通知处于wait状态,并需要处理地点
     * 的线程进行业务处理(通知方)
     */
    public synchronized void changeSite(){
        this.site="BeiJing";
        notifyAll();
    }

3. The method defined two parties waiting
explanation: Wait side:. A lock of the object acquired (plus synchronized keyword in the method, retrieves a lock on the object)
. B judges whether the cycle is not satisfied with the wait () method (determination 101 km is greater than or equal to the determination whether Beijing site is not satisfied, then it is still on the road (in the blocked state))
C. business logic execution condition is satisfied (output of only a simple operation here)

public synchronized void waitKm(){
        while(this.km <= 100){
            try {
                wait();
                System.out.println("check km thread["+
                        Thread.currentThread().getId()+"] is be notified");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("the km is "+this.km+", I will changed db.");

    }
    public synchronized void waitSite(){
        while(this.site.equals(CITY)){
            try {
                wait();
                System.out.println("check site thread["+
                        Thread.currentThread().getId()+"] is be notified");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("the km is "+this.site+", I will call user.");

    }

Express complete entity class

package 等待和通知的标准范式;

/**
 * @author lenovo
 * 快递实体类
 */
public class Express {
    //初始目的地
    public final static String CITY="ShangHai";
    //快递的里程数
    private int km;
    //快递的目的地
    private String site;

    public Express() {
    }

    public Express(int km, String site) {
        this.km = km;
        this.site = site;
    }

    /**
     * 变化公里数,然后通知处于wait状态,并需要处理公里
     * 数的线程进行业务处理(通知方)
     */
    public synchronized void changeKm(){
        this.km=101;
        notifyAll();

    }

    /**
     * 变化地点,然后通知处于wait状态,并需要处理地点
     * 的线程进行业务处理(通知方)
     */
    public synchronized void changeSite(){
        this.site="BeiJing";
        notifyAll();
    }

    public synchronized void waitKm(){
        while(this.km <= 100){
            try {
                wait();
                System.out.println("check km thread["+
                        Thread.currentThread().getId()+"] is be notified");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("the km is "+this.km+", I will changed db.");

    }
    public synchronized void waitSite(){
        while(this.site.equals(CITY)){
            try {
                wait();
                System.out.println("check site thread["+
                        Thread.currentThread().getId()+"] is be notified");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("the km is "+this.site+", I will call user.");

    }
}

Here we write a simple test class
1. Define a change in the number of miles of thread class

//检查里程数变化的线程,不满足条件线程一直等待
    private static class CheckKm extends Thread{
        @Override
        public void run() {
            express.waitKm();
        }
    }

Define a thread class location change

 //检查地点变化的线程,不满足条件线程一直等待
    private static class CheckSite extends Thread{
        @Override
        public void run() {
            express.waitSite();
        }
    }

Test class complete code
explanation: Start 3 mileage threads are changes in the main method, three threads change places, then the number of the notified party notification kilometers, look at the output

package 等待和通知的标准范式;

/**
 * @author lenovo
 */
public class TestWN {
    private static Express express=new Express(0,Express.CITY);

    //检查里程数变化的线程,不满足条件线程一直等待
    private static class CheckKm extends Thread{
        @Override
        public void run() {
            express.waitKm();
        }
    }
    //检查地点变化的线程,不满足条件线程一直等待
    private static class CheckSite extends Thread{
        @Override
        public void run() {
            express.waitSite();
        }
    }

    public static void main(String[] args) throws InterruptedException {

        for(int i=0;i<3;i++){
            new CheckKm().start();
        }
        for(int i=0;i<3;i++){
            new CheckSite().start();
        }
        Thread.sleep(100);
        express.changeKm(); //快递公里数发生变化
    }

}

operation result:

  1. notifyAll () operating results
    Here Insert Picture Description
    analysis: six threads have been notified but only three kilometers of the number of threads to continue to meet the requirement of more than 100km after their business logic ( which is consistent with what we call the notifyAll () notifies all waiting threads, while only decision condition is met to wait for their own party will continue to implement its own business logic)
    2. earlier we said that the use notify () notification, it may cause loss of signal (briefly described below)
    we Express All classes of notifyAll () methods are changed to notify ()
    result:
    Here Insert Picture Description

Explanation: The chart above shows the change in the number of km notifying party should wake of this change is the number of wait wait km square, but because random scheduling of the operating system, our notification signal is changed locations cut the thread Hu, while it has not satisfy himself above judgment 100km, so it is unable to implement its own business logic (it is now a non-waiting thread, such as thread [11] although it is awakened but not out of the loop, while waiting threads unable to notify the signals in the wait state ), this may be the so-called flood-dry drought floods death, which is obviously not what we want, where it is recommended to make use of notifyAll in development ()

Published 19 original articles · won praise 2 · Views 420

Guess you like

Origin blog.csdn.net/TheWindOfSon/article/details/103484073