2017年计算机二级考试时间:2017年计算机二级考试java章节辅导:多线程之间的通讯

副标题:2017年计算机二级考试java章节辅导:多线程之间的通讯

时间:2024-01-07 09:20:01 阅读: 最新文章 文档下载
说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。


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类到底干什么呢?

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 监视生产者

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

2017年计算机二级考试java章节辅导:多线程之间的通讯.doc

本文来源:https://www.wddqw.com/TCQI.html