本文共 3945 字,大约阅读时间需要 13 分钟。
生产者和消费者是一种经典的供求案例,生产者和消费者线程之间的关系涉及线程之间的交互。生产者线程产生的数据项,将来会被消费者消费,每个生产出来的数据会被保存在一个共享的仓库中。
假设线程以不同的速度进行,那么将会导致消费者可能获取到还未生产的数据,生产者也有可能在消费者还未取走前一条数据的前提下继续生产,这样就会造成混乱。
为了克服这种混乱,生产者线程必须等待,知道消费者取走之后通知生产者,等待解除,可以生产。如果生产者未生产数据,消费者就要一直等待,直到生产者生产完毕,唤醒消费者线程,取走生产好的数据。
以下为代码实现:
package my_application;public class ProducerConsumer { public static void main(String[] args) { ShareStorage s = new ShareStorage(); new Producer(s).start(); new Consumer(s).start(); }}class ShareStorage{ private char c; //此实例变量跟踪两个条件,生产者等待消费者消费一个数据,消费者等待生产者生产一个数据 private volatile boolean flag = true; synchronized void setShareData(char c){ while (!flag) { //消费者未取走,则生产者等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.c = c; flag = false;//设置标志位为false,告诉消费者可以消费,此时生产者等待 notify(); } synchronized char getShareData(){ while (flag) { //flag = true ,表示消费者等待,此时生产者生产 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); return c; }}class Producer extends Thread{ private final ShareStorage shareStorage; Producer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { for (char ch = 'A'; ch < 'Z'; ch++) { shareStorage.setShareData(ch); System.out.println(ch + ",生产者生产"); } }}class Consumer extends Thread{ private final ShareStorage shareStorage; Consumer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { char ch; do { ch = shareStorage.getShareData(); System.out.println(ch + ",消费者消费"); } while (ch != 'Z'); }}
此时的输出结果可能为:
O,生产者生产O,消费者消费P,生产者生产P,消费者消费
或者
A,生产者生产B,生产者生产A,消费者消费B,消费者消费
这样的输出并不表示消费者和生产者线程没有同步,这是因为setShareData(),getShareData()之后的输出没有被同步造成的结果,为了解决这个问题,加上同步块就可以完美解决这个问题了。见下面修改后的代码:
package my_application;public class ProducerConsumer { public static void main(String[] args) { ShareStorage s = new ShareStorage(); new Producer(s).start(); new Consumer(s).start(); }}class ShareStorage{ private char c; private volatile boolean flag = true;//写入取走标记 synchronized void setShareData(char c){ while (!flag) { //消费者未取走,则生产者等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.c = c; flag = false;//设置标志位为false,告诉消费者可以消费,此时生产者等待 notify(); } synchronized char getShareData(){ while (flag) { //flag = true ,表示消费者等待,此时生产者生产 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); return c; }}class Producer extends Thread{ private final ShareStorage shareStorage; Producer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { for (char ch = 'A'; ch < 'Z'; ch++) { synchronized (shareStorage) { shareStorage.setShareData(ch); System.out.println(ch + ",生产者生产"); } } }}class Consumer extends Thread{ private final ShareStorage shareStorage; Consumer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { char ch; do { synchronized (shareStorage) { ch = shareStorage.getShareData(); System.out.println(ch + ",消费者消费"); } } while (ch != 'Z'); }}
输出结果:
A,生产者生产A,消费者消费B,生产者生产B,消费者消费C,生产者生产C,消费者消费D,生产者生产D,消费者消费E,生产者生产E,消费者消费...
转载地址:http://pdrji.baihongyu.com/