Wait () / notify () is not working properly

I have a ConsumerProducer object on which I want to get a lock from two different threads. The class is as follows:

public class ConsumerProducer {

    public String stringPool = null;

    public void put(String s){
        stringPool = s;
    }

    public String get(){
        String ret = stringPool;
        stringPool = null;
        return ret;
    }

}

The thread impl class is as follows:

public class WaitNotifyTest implements Runnable {

    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 1;

    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }

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

        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);

        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

    @Override
    public void run() {
        while (true) {

            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            } else {
                synchronized (cp) {
                    try {
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }
            i++;
        }
    }

    public void consume() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }

    public void produce() {
        System.out.println("getting: " + cp.get());
    }

}

But when I run the code, it encounters some kind of dead end, and it gets stuck, for example,

Putting: Counter3
notify from Consumer

Something is going terribly wrong, but I can’t determine. Please, help.

+4
source share
2 answers

Your consumer does the work of the manufacturer, and the manufacturer does the work with the consumer. Sharing their responsibilities and changing the waiting conditions. Please see the code below.

  • , , cp. .
  • , , . cp. , .
  • - , .
  • - .
  • . Counter 1 5, ++ Producer. ?
  • , , get() cp, null stringPool. . clearString(), , .

    public class WaitNotifyTest implements Runnable {
    
    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 0;
    
    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }
    
    public static void main(String[] args) throws InterruptedException {
    
        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
    
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);
    
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
    
    @Override
    public void run() {
        while (true) {
            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        /*
                         * Consumer will wait when there is nothing to get and he will release the lock of cp.
                         * So that producer has change to go into the synchronized block.
                         */
    
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
            } else {
                synchronized (cp) {
                    try {
                        /*
                         * Producer only produce when there is nothing or he will wait. At the same time, he will release the lock of cp.
                         * So that consumer has chance to go into the synchronized block.
                         */
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        i++;
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }
    
        }
    }
    
    public void consume() {
        System.out.println("getting: " + cp.get());
        cp.clearString();
    }
    
    public void produce() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }}
    

. ConsumerProducer.

public class ConsumerProducer {
        public String stringPool = null;

        public void put(String s){
            stringPool = s;
        }

        public String get(){
            return stringPool;
        }

        public void clearString(){
            stringPool = null;
        }
}
+1

: ConsumerProducer.java:
   ConsumerProducer {

    public volatile String stringPool = null;

    public void put(String s){
        this.stringPool = s;
    }

    public String get(){
        String ret = this.stringPool;
        //this.stringPool = null;
        return ret;
    }
    //added
    public void clearString(){
        this.stringPool = null;
    }

}

WaitNotifyTest.java    WaitNotifyTest Runnable {

    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 0;

    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }

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

        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);

        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }

    @Override
    public void run() {
        while (true) {

            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            } else {
                synchronized (cp) {
                    try {
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        i++;
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }

        }
    }

    public void produce() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }

    public void consume() {
        System.out.println("getting: " + cp.get());
        cp.clearString();
    }

}
0

Source: https://habr.com/ru/post/1648935/


All Articles