Search code examples
javaconcurrencyproducer-consumer

Producer Consumer module just outputting null


I tried making a producer consumer Java program but it doesn't seem to be working: It just doesn't terminate, the terminal just stays like this: this I want the code to print Text 1 then Text 2 then Text 3 all on new lines. I want the write thread to write the text to print, then the read thread to actually print the text. My code is down below. Also another question I have is when would this sort of model be used and is it worth learning at the moment as a beginner Java programmer. Thanks. Heres the code:

public class Test {
    public static void main(String[] args) {
        Model model = new Model();
        new Thread(new ModelThreadWriter(model)).start();
        new Thread(new ModelThreadReader(model)).start();
        
    }
}

class Model {
    private String data;
    private boolean isEmpty = true;

    public synchronized void writeData(String data) {
        while (!isEmpty) {
            try {
                wait();
            } catch (InterruptedException e) {

            }
            this.data = data;
            isEmpty = false;
            notifyAll();
        }
    }

    public synchronized String readData() {
        while (isEmpty) {
            try {
                wait();
            } catch (InterruptedException e) {

            }
        }
        isEmpty = true;
        notifyAll();
        return data;
    }
}

class ModelThreadWriter implements Runnable {
    private Model model;

    public ModelThreadWriter(Model model) {
        this.model = model;
    }
    
    @Override
    public void run() {
        String[] text = {
            "Text 1",
            "Text 2",
            "Text 3"
        };

        for (int i=0; i<text.length; i++) {
            model.writeData(text[i]);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }
        model.writeData("done");

        
    }
}

class ModelThreadReader implements Runnable {
    private Model model;

    public ModelThreadReader(Model model) {
        this.model = model;
    }

    @Override
    public void run() {
        for (String msg = model.readData(); !(msg == "done"); model.readData()) {
            System.out.println(msg);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                
            }
        }
    }
}

Solution

  • There are several errors in your code.

    1.In writeData method, this.data = data;isEmpty = false;notifyAll(); should move out of the while loop.

    2.In ModelThreadReader, == => equals.

    3.In ModelThreadReader, for (String msg = model.readData(); !(msg == "done"); model.readData()) => !(msg.equals("done")); msg = model.readData(), otherwise it's going to print out Text1 every time.

    class Model {
        private String data;
        private boolean isEmpty = true;
    
        public synchronized void writeData(String data) {
            while (!isEmpty) {
                try {
                    wait();
                } catch (InterruptedException e) {
    
                }
            }
            this.data = data;
            isEmpty = false;
            notifyAll();
        }
    
        public synchronized String readData() {
            while (isEmpty) {
                try {
                    wait();
                } catch (InterruptedException e) {
    
                }
            }
            isEmpty = true;
            notifyAll();
            return this.data;
        }
    }
    
    class ModelThreadWriter implements Runnable {
        private Model model;
    
        public ModelThreadWriter(Model model) {
            this.model = model;
        }
    
        @Override
        public void run() {
            String[] text = {
                "Text 1",
                "Text 2",
                "Text 3"
            };
            for (int i=0; i<text.length; i++) {
                model.writeData(text[i]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
                }
            }
            model.writeData("done");
        }
    }
    
    class ModelThreadReader implements Runnable {
        private Model model;
    
        public ModelThreadReader(Model model) {
            this.model = model;
        }
    
        @Override
        public void run() {
            String msg = model.readData();
            for (; !(msg.equals("done")); msg = model.readData()) {
                System.out.println(msg);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
                }
            }
        }
    }