Three ways to realize producers and consumers

Posted by joinx on Wed, 25 Mar 2020 16:42:12 +0100

  1. synchronized + wait + notify is saved using an array. Arrays are run by empty producers, and then invoked by notify to wake consumers and wait for them. Consumers complete consumption, wake up producers and wait for themselves.

  2. ReentrantLock reenters the lock.

  3. ReentrantLock is still used at the bottom of BlockingQueue

Special value column: if the queue is full or empty, the operation will fail. The return value is the result of the operation

block column: if the queue is full or empty, it will wait

Throws exception column: if the queue is full or empty, an exception will be thrown

public class WaitConsumerProducer {

    private String[] list = new String[10];
    private int cursor = -1;

    public void produce() throws InterruptedException {
        synchronized (this) {

            if (cursor >= 0) {
                this.wait();
            }

            while (cursor < list.length - 1) {
                list[++cursor] = "production" + cursor;
            }

            this.notifyAll();
        }
    }

    public void consume() throws InterruptedException {
        synchronized (this) {

            if (cursor < 0) {
                this.wait();
            }

            while (cursor >= 0) {
                System.out.println(list[cursor--]);
            }

            Thread.sleep(1000);
            this.notifyAll();
        }
    }
}

public class ReentrantConsumerProducer {
    private String[] list = new String[10];
    private int cursor = -1;

    private ReentrantLock lock = new ReentrantLock();

    public void produce() {
        lock.lock();
        try {
            // Put it in front of the lock and it will deadlock
            if (cursor >= 0) {
                return;
            }
            while (cursor < list.length - 1) {
                list[++cursor] = "commodity" + cursor;
            }
        } finally {
            lock.unlock();
        }
    }

    public void consume() {
        lock.lock();

        try {
            // Put it in front of the lock and it will deadlock
            if (cursor < 0) {
                return;
            }
            while (cursor >= 0) {
                Thread.sleep(200);
                System.out.println(list[cursor--]);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public static void blockingQueue() {
    final LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();

    new Thread(() -> {
        while (true) {
            queue.add("commodity");
        }
    }).start();

    new Thread(() -> {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(queue.poll());
        }
    }).start();
}

Topics: Oracle Java