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

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,通知生产者生产...

时间: 2024-10-08 22:40:56

线程通信(生产者与消费者问题)的相关文章

Java多线程-同步:synchronized 和线程通信:生产者消费者模式

大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同步:synchronized 多个线程同时访问一个对象,可能造成非线程安全,数据可能错误,所谓同步:就是控制多个线程同时访就是控制多线程操作同一个对象时,注意是同一个对象,数据的准确性, 确保数据安全,但是加入同步后因为需要等待,所以效率相对低下. 如:一个苹果,自己一个人去咬怎么都不会出问题,但是

Java线程通信-生产者消费者问题

线程通信示例--生产者消费者问题 这类问题描述了一种情况,假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费.假设仓库中没有产品,则生产者可以将 产品放入仓库,有产品,则停止生产并等待,直到仓库中的产品被消费这取走为止. 如果仓库中放油产品,则消费者可以将产品取走消费,否则停止消费并等待,直到 仓库中再次放入产品为止. 显然,这是一个同步问题,生产者和消费这共享同一资源, 并且生产者和消费这之间彼此依赖,互为条件向前推进.Java提供了3个方法解决了线程间的

Java---19---多线程:生产者和消费者

生产者和消费者问题是多线程通信的经典问题.这类问题描述了这样一种情况:假设有一个仓库,用来存储产品,有生产者负责生产产品,有消费者负责消费.生产者生产的产品存放在仓库之中,消费者从仓库之中取出产品.显然这是一个同步问题,生产者和消费者共享同一资源,并且生产者和消费者之间彼此依赖,互为条件向前推进.那么,该如何编写代码来实现呢? class Resource { private String name; private String sex; private boolean flag = fals

Java---20---多线程:生产者和消费者2(JDK1.5升级版)

此篇文章写的是JDK1.5升级版的生产者和消费者. Java 升级之后的解决方法: Lock java.util.concurrent.locks 接口 Lock 所有已知实现类: ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock public interface Lock Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作.此实现允许更灵活的结构,可

生产者、消费者模型

转载地址:http://blog.csdn.net/snow_5288/article/details/72794306 一.概念引入 日常生活中,每当我们缺少某些生活用品时,我们都会去超市进行购买,那么,你有没有想过,你是以什么身份去的超市呢?相信大部分人都会说自己是消费者,确实如此,那么既然我们是消费者,又是谁替我们生产各种各样的商品呢?当然是超市的各大供货商,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的超市又该作何理解呢?诚然,它本身是作为一座交

Java多线程--生产者与消费者问题

说明 Java中,线程之间的通信主要是由java.lang.Object类提供的wait.notify和notifyAll这3个方法来完成: ①对象的wait方法被调用后,线程进入对象的等待队列中,并释放对象锁,其它线程可以竞争使用此对象锁:sleep方法使得一个线程进入睡眠状态,但是线程所占有的资源并没有释放. ②当对象的notify方法被调用,该方法会从对象的等待队列中随机取出一个线程来唤醒:notifyAll是唤醒等待队列中所有线程,这些线程会与其它正在执行的线程共同竞争对象锁. ③wai

多线程-线程间通信-多生产者多消费者示例

1.多线程-线程间通信-多生产者多消费者问题 多生产者和多消费者.等待唤醒机制. 产生了两个问题: 1.出现了多次连续生产,未消费,或者一个商品被消费多次. 解决:必须要--------每一个被唤醒的线程判断一次标记,所以将if判断改为while判断. 2.出现了死锁. 本方唤醒了本方,导致了所有的线程都等待了. 解决方式就是:唤醒所有等待的线程.这样既唤醒了本方也唤醒对方. 虽然解决了多生产消费的问题,但是有些低效. 解决方法一: 唤醒所有等待的线程 class Resource{     p

java多线程同步以及线程间通信详解&amp;消费者生产者模式&amp;死锁&amp;Thread.join()(多线程编程之二)

本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: [java] view plain copy print? package com.zejian.test; /** * @author zejian * @time 2016年3月12日 下午2:55:42 * @decrition 模拟卖票线程 */ public class Ticket implements Runnable { //当前拥有的票数 private 

java基础——线程通信机制,生产者消费者

package communication; /* 使用两个线程1,2交替打印1-100 线程通信方法: 1.wait():一旦执行此方法,当前线程进入阻塞态,并释放锁 2.notify():会唤醒被wait的一个线程,如果有多个线程wait,则唤醒优先级高的 3.notifyAll():唤醒所有被wait的线程 说明: 1.wait(),notify(),notifyAll()使用在同步代码块或同步方法中,不能用在lock方法中 2.这三个方法的调用者必须是同步代码块或同步方法中的锁对象(同步