当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
2015年计算机二级Java多线程之间的通讯学习教程
发布时间:2011/12/28 9:49:13 来源:城市学习网 编辑:ziteng

7.3 多线程之间的通讯

  7.3.1 生产者和消费者

  多线程的一个重要特点是它们之间可以互相通讯。你可以设计线程使用公用对象,每个线程都可以独立操作公用对象。典型的线程间通讯建立在生产者和消费者模型上:一个线程产生输出;另一个线程使用输入。

  buffer让我们创建一个简单的"Alphabet Soup"生产者和相应的消费者.

  7.3.2 生 产 者

  生产者将从thread类里派生:

  class Producer extends Thread {

  private Soup soup;

  private String alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  public Producer(Soup s) {

  //Keep our own copy of the shared object

  this.soup = s;

  }

  public void run() {

  char c; //Throw 10 letters into the soup

  for (int i=0;i<10;i++) {

  c = alphabet.charAt((int)(Math.random() *26));

  soup.add(c); //print a record of osr addition

  System.out.println("Added"+c + "to the soup.");

  //wait a bit before we add the next letter

  try {

  sleep((int)(Math.random() *1000));

  }

  catch (InterruptedException e) {

   //

  }

  }

  }

  }

  注意我们创建了Soup类的一个实例。生产者用soup.add()函数来建立字符池。

  7.3.3 消费者

  让我们看看消费者的程序:

  public class Consumer extends Thread {

  private Soup soup;

  public Consumer (Soup s) {

  //keep our own copy of the shared object

  this.soup = s;

  }

  public void run() {

  char c;

  //Eat 10 letters from the alphabet soup

  for (int I=0 ;i<10;i++) {

  //grab one letter

  this.c = soup.eat();

  //Print out the letter that we retrieved

  System.out.println("Ate a letter: " +c); //

  try {

  sleep((int)(Math.raddom()*2000));

  }

  catch (InterruptedException e) {

  }

  ` }

  }

  }

  同理,象生产者一样,我们用soup.eat()来处理信息。那么,Soup类到底干什么呢?[NextPage]

  7.3.4 监 视

  Soup类执行监视两个线程之间传输信息的功能。监视是多线程中不可缺少的一部分,因为它保持了通讯的流畅。让我们看看Soup.java文件:

  public class Soup {

  private char buffer[] = new char[6];

  private int next = 0; //Flags to keep track of our buffer status

  private boolean isFull = false;

  private boolean isEmpty = true;

  public syschronized char eat() {

  //We can't eat if there isn't anything in the buffer

  while (isEmpty == true) {

  try {

  wait() ;//we'll exit this when isEmpty turns false

  catch (InterruptedException e) {

  }

  }

  //decrement the count,since we're going to eat one letter next--;

  //Did we eat the last letter?

  if (next== 0) {

  isEmpty = true;

  }

  //We know the buffer can't be full,because we just ate

  isFull = false;

  notify(); //return the letter to the thread that is eating

  return (buffer[next]);

  }

  //method to add letters to the buffer

  public synchronized void add(char c) {

  //Wait around until there's room to add another letter

  while (isFull == true ) {

  try{

  wait();//This will exit when isFull turns false

  }

  catch (InterruptedException e) {

  }

  } // add the letter to the next available spot

  buffer[next]=c; // Change the next available spot

  next++; // Are we full;

  if (next ==6) {

  isFull =true;

  }

  isEmpty =false;

  notify();

  }

  }

  soup类包含两个重要特征:数据成员buffer[]是私有的,功能成员add()和eat()是公有的。

  数据私有避免了生产者和消费者直接获得数据。直接访问数据可能造成错误。例如,如果消费者企图从空缓冲区里取出数据,你将得到不必要的异常,否则,你只能锁住进程。同步访问方法避免了破坏一个共享对象。当生产者向soup里加入一个字母时,消费者不能吃字 符,诸如此类。这种同步是维持共享对象完整性的重要方面。notify()函数将唤醒每一个等待线程。等待线程将继续它的访问。

  7.3.5 联系起来

  现在我们有一个生产者,一个消费者和一个共享对象,怎样实现它们的交互呢? 我们只需要一个简单的控制程序来启动所有的线程并确信每一个线程都是访问的同一个共享对象。下面是控制程序的代码:

  SoupTest.java:

  class SoupTest {

  public static void main(String args[]) {

  Soup s = new Soup();

  Producer p1 = new Producer(s);

  Consumer c1 = new Consumer(s);

  p1.start();

  c1.start();

  }

  }

  7.3.6 监视生产者

  生产者/消费者模型程序经常用来实现远程监视功能,它让消费者看到生产者同用户的交互 或同系统其它部分的交互。 例如,在网络中,一组生产者线程可以在很多工作站上运行。 生 产者可以打印文档,文档打印后,一个标志将保存下来。一个(或多个消费者将保存标志并 在晚上报告白天打印活动的情况。另外,还有例子在一个工作站是分出几个独立的窗口。 一 个窗口用作用户输入(生产者的另一个窗口作出对输入的反应消费者的。

广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved