Doubt: Multi-production and multi-consumption operation value - suspended animation from: "JAVA Multi-threaded Programming Core Technology" 3.1.11.2

JDK: 1.8
Background:
When I tested the multi-production and multi-consumption operation values ​​- suspended animation, there were two production and consumption threads respectively, and each thread looped the corresponding method twice.
Problem :
Print the log and found that consumption 2 has a wait before it wakes up Then it went down and executed, I don't know why?
Attach the test code
first . There is always
consumer 2 WAITING 0 in the log. Releasing value=null
Consumer 2 WAITING 1

Normal release of value is followed by value, but this time it does not. Although it does not affect the function, it is very strange.
/**
 * 3.1.11.2 Multi-production and multi-consumption operation value - suspended animation
 * Created by ironlee on 17/12/23.
 */
public class ProducerAndConsumerAllWait {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    /**
     * Production
     * @param lock
     */
    public void producer(Object lock){
        synchronized (lock){
            try {
                int i = 0 ;
                while(StringUtils.isNotBlank(getValue())) {
                    System.out.println(Thread.currentThread().getName()+" WAITING value="+getValue()+" "+(i++));
                    lock.wait();
                }
                String value = System.currentTimeMillis()+"-"+System.nanoTime();
                System.out.println(Thread.currentThread().getName()+" RUNNABLE value="+value);
                setValue(value);
                lock.notify();
//                System.out.println(System.currentTimeMillis()+"-"+System.nanoTime()+" 生产者 "+Thread.currentThread().getName()+" NOTIFY value="+getValue());
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
        }
    }

    /**
     * Consumption
     * @param lock
     */
    public void consumer(Object lock){
        synchronized (lock){
            try{
                int i = 0 ;
// Why didn't wake up wait to go down?
                while(StringUtils.isBlank(getValue())){
                    System.out.println(Thread.currentThread().getName()+" WAITING "+(i));
                    lock.wait();
                    System.out.println(Thread.currentThread().getName()+" WAITING "+(i) + " 解除 value="+getValue());
                    i++;

                }
                System.out.println(Thread.currentThread().getName()+" RUNNABLE value="+getValue());
                setValue(null);
                lock.notify();
//                System.out.println(System.currentTimeMillis()+"-"+System.nanoTime()+" 消费者 "+Thread.currentThread().getName()+" NOTIFY value="+getValue());
            }catch(InterruptedException e){
                e.printStackTrace ();
            }
        }
    }

    public static void main(String[] args) {
        final Object lock = new Object();
        final ProducerAndConsumerAllWait domain = new ProducerAndConsumerAllWait();
        final int count = 2;
        Runnable producer = new Runnable() {
                    @Override
                    public void run() {
                        synchronized (lock){
                            int i = 0 ;
                            while( i < count ){
                                System.out.println( Thread.currentThread().getName()+" 序号="+i);
                                domain.producer( lock );
                                i++;
                            }
                        }
                    }
                };
        Runnable consumer = new Runnable() {
                    @Override
                    public void run() {
                        synchronized (lock){
                            int i = 0 ;
                            while(i< count){
                                System.out.println( Thread.currentThread().getName()+" 序号="+i);
                                domain.consumer( lock );
                                i++;
                            }
                        }
                    }
                };
                for (int ii = 0; ii <2; ii ++) {
                    Thread producerT = new Thread(producer);
                    producerT.setName("Producer"+(ii+1));
                    producerT.start ();
                    Thread consumerT = new Thread(consumer);
                    consumerT.setName("Consumer"+(ii+1));
                    consumerT.start();
                }
        try {
            Thread.sleep( 1000L );
        } catch (InterruptedException e) {
            e.printStackTrace ();
        }
        Thread[] threadArray = new Thread[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate( threadArray );
        for( Thread t : threadArray ){
            System.out.println( t.getName() + " " + t.getState() );
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326489336&siteId=291194637