线程通信(生产者与消费者问题)

1、线程通信的必要性

    多线程不仅共享资源,而且相互牵制向前运行。

2、线程通信的方法(都是在Object中定义)

    3个方法:

                1)    wait() 可运行转入阻塞状态,放锁

                2)    notify() 阻塞转入可运行状态,获得锁

                3)    notifyAll() 所有调用wait方法而被挂起的线程重新启动,有个条件:wait与notifyAll必须是属于同一个对象

    必须在同步方法或同步代码块中使用

3、共享资源类(仓库)

    注:共享资源(产品),牵制信息(产品有无)

 package com.ljb.app.communication;
/**
 * 共享资源类
 * @author LJB
 * @version 2015年3月11日
 */
public class ShareData {
 // 产品
 private char c;
 
 // 牵制信息(产品有无,开始时仓库中没有产品)
 private boolean isProduced = false;
 
 /*
  * 放产品(生产产品)
  */
 public synchronized void putShareChar (char c) {
  // 如果消费者还没有消费或者仓库中有产品,则生产者等待
  if (isProduced) {
   System.out.println("消费者还未消费,因此生产者停止生产。");
   try {
    wait();// 生产者等待
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  
  // 仓库中放入生产的产品
  this.c = c;
  
  // 改变信号量(有产品)
  isProduced = true;
  
  // 通知消费者消费
  notify();
  System.out.println("生产者生产了产品" + c + ",通知消费者消费...");
 }
 
 /*
  * 取产品(消费产品)
  */
 public synchronized char getShareChar () {
  // 如果生产者还未生产或者仓库中没有产品,则消费者等待
  if (!isProduced) {
   System.out.println("生产者还未生产,因此消费者停止消费。");
   try {
    wait();// 消费者等待
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  
  // 改变信号量(没有产品或者消费了该产品)
  isProduced = false;
  
  // 通知生产者生产
  notify();
  System.out.println("消费者消费了产品" + c + ",通知生产者生产...");
  
  return this.c;
 }
}

4、生产者线程

 package com.ljb.app.communication;
/**
 * 生产者线程,每隔一段时间生产一个产品
 * @author LJB
 * @version 2015年3月11日
 */
public class Producer extends Thread{
 // 共享资源对象
 private ShareData s;
 
 // 有参构造方法
 public Producer (ShareData s) {
  this.s = s;
 }
 
 public void run () {
  for (char ch = 'A' ; ch <= 'D' ; ch++) {
   try {
    Thread.sleep((int)(Math.random()*3000));
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   s.putShareChar(ch);// 将产品放入仓库
  }
 }
}

5、消费者线程

 package com.ljb.app.communication;
/**
 * 消费者线程
 * @author LJB
 * @version 2015年3月11日
 */
public class Consumer extends Thread{
 // 共享资源
 private ShareData s;
 
 // 构造方法
 public Consumer (ShareData s) {
  this.s = s;
 }
 
 public void run () {
  char ch;
  do {
   try {
    Thread.sleep((int)(Math.random()*3000));
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   ch = s.getShareChar();// 从仓库中取出产品
  } while (ch != 'D');
 }
}

6、测试类

 package com.ljb.app.communication;
/**
 * 测试类
 * @author LJB
 * @version 2015年3月11日
 */
public class Test {
 /**
  * @param args
  */
 public static void main(String[] args) {
  ShareData s = new ShareData();
  
  Thread consumer = new Consumer(s);
  consumer.start();
  
  Thread producer = new Producer(s);
  producer.start();
 }
}

运行结果:

生产者还未生产,因此消费者停止消费。
生产者生产了产品A,通知消费者消费...
消费者消费了产品A,通知生产者生产...
生产者生产了产品B,通知消费者消费...
消费者消费了产品B,通知生产者生产...
生产者生产了产品C,通知消费者消费...
消费者消费了产品C,通知生产者生产...
生产者生产了产品D,通知消费者消费...
消费者消费了产品D,通知生产者生产...

转载于:https://my.oschina.net/u/2320342/blog/385195

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值