Java 生产者消费者问题

1 一个生产者一个消费者

生产者和消费者同步获取存放产品的队列

生产者在生产后通知消费者,在队列满时等待消费者取出

消费者在取出后通知生产者,在队列为空时等待生产者放入

  • 场景类
import java.util.LinkedList;
import java.util.Queue;

public class Client {
    public static void main(String[] args) throws InterruptedException {
        Queue<String> queue = new LinkedList<>();
        Producer p = new Producer(queue);
        Customer c = new Customer(queue);
        p.start();
        c.start();
    }
}
  • 生产者
package t11;

import java.util.Queue;

public class Producer extends Thread {
    private final Queue<String> queue;

    public Producer(Queue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run(){
        while (true) {
            synchronized (queue) {
                if (queue.size() > 4) {
                    System.out.println("队列已满,等待C");
                    try {
                       queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                queue.add("sss");
                System.out.println("P放入队列,队列大小:" + queue.size());
                queue.notify();
            }
            try {
                int a = (int) (Math.random() * 100);
                Thread.sleep(a);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 消费者
package t11;

import java.util.LinkedList;
import java.util.Queue;

public class Customer extends Thread {
    private final Queue<String> queue;

    public Customer(Queue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                if (queue.isEmpty()) {
                    System.out.println("队列为空,等待P");
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                queue.poll();
                System.out.println("C取出队列,队列大小:" + queue.size());
                queue.notify();
            }
            try {
                int a = (int) (Math.random() * 100);
                Thread.sleep(a);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2 多个生产者多个消费者

继续使用上面的代码,会出现“假死”的情况。

三个生产者,一个消费者;由于生产者生产完后没有激活消费者,而是激活另外一个消费者,导致所有线程都堵塞了。
P0 队列已满等待
P2 队列已满等待
C0 C取出队列,队列大小:0
C0 队列为空等待
P1 P放入队列,队列大小:1
P0 队列已满等待
P1 队列已满等待
P2 队列已满等待

将notify()方法改为notifyAll()方法,让生产者生产完后激活所有线程(队列满时,其他生产者在执行过程中会自动堵塞,从而消费者开始运行)。

场景类:

public class Client {
    public static void main(String[] args) throws InterruptedException {
        Queue<String> queue = new LinkedList<>();
        Producer[] producers = new Producer[3];
        Customer[] customers = new Customer[1];

        for (int i = 0; i < producers.length; i++) {
            producers[i] = new Producer(queue);
            producers[i].setName("P" + i);
        }
        for (int i = 0; i < producers.length; i++) {
            producers[i].start();
        }

        for (int i = 0; i < customers.length; i++) {
            customers[i] = new Customer(queue);
            customers[i].setName("C" + i);
        }
        for (int i = 0; i < customers.length; i++) {
            customers[i].start();
        }
    }
}

生产者:

public class Producer extends Thread {
    private final Queue<String> queue;
    private static final int capactiy = 1;

    public Producer(Queue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                try {
                    if (queue.size() >= capactiy) {
                        System.out.println(Thread.currentThread().getName() + " 队列已满等待");
                        queue.wait();
                    } else {
                        queue.add("sss");
                        System.out.println(Thread.currentThread().getName()
                                + " P放入队列,队列大小:" + queue.size());
                        queue.notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                int a = (int) (Math.random() * 100);
                Thread.sleep(a);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者:

public class Customer extends Thread {
    private final Queue<String> queue;

    public Customer(Queue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                try {
                    if (queue.isEmpty()) {
                        System.out.println(Thread.currentThread().getName() + " 队列为空等待");
                        queue.wait();
                    } else {
                        if (queue.poll() == null) {
                            System.out.println("对列为空,无法出队");
                            System.exit(1);
                        } else {
                            System.out.println(Thread.currentThread().getName()
                                    + " C取出队列,队列大小:" + queue.size());
                            queue.notifyAll();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                int a = (int) (Math.random() * 100);
                Thread.sleep(a);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(Java,java,多线程,生产者消费者)