生产者和消费者问题是多线程通信的经典问题。这类问题描述了这样一种情况:假设有一个仓库,用来存储产品,有生产者负责生产产品,有消费者负责消费。生产者生产的产品存放在仓库之中,消费者从仓库之中取出产品。显然这是一个同步问题,生产者和消费者共享同一资源,并且生产者和消费者之间彼此依赖,互为条件向前推进。那么,该如何编写代码来实现呢?
class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name, String sex) { if (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name = name + "--" + sex; System.out.println(Thread.currentThread().getName() + "--生产者--" + this.name); flag = true; notify(); } public synchronized void out() { if (flag == false) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "---消费者---" + this.name); flag = false; notify(); } } class Producer implements Runnable { private Resource resource; private int num = 0; Producer(Resource resource) { this.resource = resource; } public void run() { while (true) { if (num == 1) { resource.set("丽丽", "女女女"); } else { resource.set("mike", "man"); } num = ++num % 2; } } } class Consumer implements Runnable { private Resource resource; Consumer(Resource resource) { this.resource = resource; } public void run() { while (true) { resource.out(); } } } class Communicate { public static void main(String[] args) { Resource resource = new Resource(); Producer pro = new Producer(resource); Consumer con = new Consumer(resource); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); t1.start(); t2.start(); } }
这个例子已经实现了生产一个就消费一个,其实这个例子就是上一篇文章中的例子,只是将代码略作优化。
但是还有一个问题,这个例子只是一个线程用来生产,一个线程用来消费,那如果多加几个线程呢?
那我们多加上几个线程试试。
class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name, String sex) { if (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name = name + "--" + sex; System.out.println(Thread.currentThread().getName() + "--生产者--" + this.name); flag = true; notify(); } public synchronized void out() { if (flag == false) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "---消费者---" + this.name); flag = false; notify(); } } class Producer implements Runnable { private Resource resource; private int num = 0; Producer(Resource resource) { this.resource = resource; } public void run() { while (true) { if (num == 1) { resource.set("丽丽", "女女女"); } else { resource.set("mike", "man"); } num = ++num % 2; } } } class Consumer implements Runnable { private Resource resource; Consumer(Resource resource) { this.resource = resource; } public void run() { while (true) { resource.out(); } } } class Communicate { public static void main(String[] args) { Resource resource = new Resource(); Producer pro = new Producer(resource); Consumer con = new Consumer(resource); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } }
在打印结果中我们发现会有这种情况:
Thread-1--生产者--mike--man
Thread-0--生产者--mike--man
Thread-2---消费者---mike--man
还可能会发生生产一个而消费两个的情况。出现的原因在 wait()这,就不过多的解释了。
只需要将判断flag 的if 改为while 同时将notify改为notifyAll() 就ok。
修改完如下:
class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name, String sex) { while (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name = name + "--" + sex; System.out.println(Thread.currentThread().getName() + "--生产者--" + this.name); flag = true; notifyAll(); } public synchronized void out() { while (flag == false) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "---消费者---" + this.name); flag = false; notifyAll(); } } class Producer implements Runnable { private Resource resource; private int num = 0; Producer(Resource resource) { this.resource = resource; } public void run() { while (true) { if (num == 1) { resource.set("丽丽", "女女女"); } else { resource.set("mike", "man"); } num = ++num % 2; } } } class Consumer implements Runnable { private Resource resource; Consumer(Resource resource) { this.resource = resource; } public void run() { while (true) { resource.out(); } } } class Communicate { public static void main(String[] args) { Resource resource = new Resource(); Producer pro = new Producer(resource); Consumer con = new Consumer(resource); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } }
时间: 2024-11-05 12:24:47