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正在阅读:
2017年计算机二级考试java章节辅导:多线程之间的通讯01-07
材料采购工作述职报告07-25
面对不幸作文600字07-22
陕西二本文科大学排名及分数线|陕西二本文科大学排名11-17
资料员年度工作总结大全10篇09-12
军训日记500字高一【三篇】07-27
[中国证券投资基金业协会首页]中国证券投资基金业协会:2021年10月江西基金从业资格准考证打印入口已开通09-03
有一种失败叫成功作文500字08-01
2020山西大学附属中学晋中学校(晋中广安中学校)教师招聘公告01-25
信任与怀疑的PK作文800字01-26
十年后的我作文500字07-26