理论教育 Java程序设计:线程通信实例和结果

Java程序设计:线程通信实例和结果

时间:2023-10-18 理论教育 版权反馈
【摘要】:图12.21程序运行结果从图12.21的运行结果可以看出,提示object.wait()出现异常,因为对象object的控制权在main线程中。编写多线程实现多个顾客买包子案例。图12.23程序运行结果从图12.23的程序运行结果中可以看到,当顾客要买包子时,因为默认包子数为0,因此表示顾客的线程因包子数量不足进入等待状态。当包子剩余数量超过20个时,为了避免产品堆积,表示老板的线程进入等待状态,等待顾客消费。

Java程序设计:线程通信实例和结果

在前面介绍了关于线程同步的相关知识,而在现实中除了考虑线程之间的同步,很多时候还需要线程之间的协作。比如两个线程分别负责奇数和偶数的输出,还有经典的“生产者-消费者”模型都是需要线程之间进行协作的。

Java中有很多方式可以实现线程的通信,这里将介绍Java中Object类中的wait()、notify()和notifyAll()方法来实现线程通信。

wait()方法可以使线程从运行状态进入就绪状态,并释放对象锁。

notify()方法能够唤醒一个因wait()方法进入阻塞状态的线程,解除线程的阻塞状态。

notifyAll()方法可以唤醒因wait()方法进入阻塞状态的所有线程。

提示:

wait()方法和sleep()方法都可以让线程进入等待状态,但wait()方法会释放对象锁,sleep()方法不会释放对象锁。

在使用wait()方法和notify()方法之前,需要先了解对象的控制权(monitor)。因为只有线程拥有某个对象的控制权,才能执行这个对象的wait()方法和notify()方法。

如下面的代码:

运行上述代码,将输出如图12.21所示结果。

图12.21 程序运行结果

从图12.21的运行结果可以看出,提示object.wait()出现异常,因为对象object的控制权在main线程中。所以,无论是执行对象的wait()、notify()方法还是notifyAll()方法,都必须保证当前运行的线程取得了该对象的控制权。如果在没有控制权的线程中执行对象的wait()、notify()或notifyAll()方法,将抛出java.lang.IllegalMonitorStateException异常。

要获得对象的控制权,可以通过同步锁来实现,如synchronized 代码块。将上述代码修改为如下代码,程序将正常运行。

说明:

在Java中任何一个时刻,对象的控制权只能被一个线程拥有。(www.daowen.com)

【例12.13】编写两个线程,一个线程输出奇数1,3,5,7,9,另一个线程输出偶数2,4,6,8,10,并且要求控制台的输出顺序为1,2,3,4,5…10。

在Chapter12项目的src目录下新建一个名为cn.pzhu.WaitAndNotify的包,然后在这个包下面创建一个名为Demo01的类,关键代码如下:

在上述代码中,编写了一个线程ThreadA用来输出1~10的奇数,编写了一个线程ThreadB用来输出1~10的偶数。两个线程的run()方法中使用了同步代码块用于获取flag对象锁,程序的输出结果如图12.22所示。

图12.22 程序运行结果

从图12.22可以看出,两个线程交替执行,线程Thread-0输出一个奇数之后,将执行flag.wait(),释放flag对象锁并使当前线程进入等待状态;之后线程Thread-1获得flag对象锁开始执行,输出偶数之后再释放flag对象锁进入等待状态。两个线程交替执行,最后控制台按序输出1~10。

下面再看看经典的“生产者-消费者”模型是如何进行线程之间的协作的。

“生产者-消费者”模型指的是一些线程充当生产者负责生产产品,一些线程充当消费者负责消费产品,在线程的运行过程中往往会出现“供大于求”或“求大于供”的现象。这就要求当生产队列为空时,消费者就需要等待产品,并在等待期间释放对临界资源的占有权,然后生产者获得对临界资源的占有权并开始生产产品,在生产产品之后通知消费者开始消费。同理,当队列满时,生产者就需要等待,直到队列有空闲空间(或产品消费完毕、或消费至设定的产品数)时,消费者再通知生产者开始生产。

【例12.14】 编写多线程实现多个顾客买包子案例。编写Consumer线程来模拟顾客买包子,编写Product线程来模拟老板做包子,在main线程中启动一个Product线程和两个Consumer线程来模拟老板和两个顾客的买卖过程。

在cn.pzhu.WaitAndNotify包下面创建一个名为Demo02的类,关键代码如下:

运行上述代码,程序结果如图12.23所示。

图12.23 程序运行结果

从图12.23的程序运行结果中可以看到,当顾客要买包子时,因为默认包子数为0,因此表示顾客的线程因包子数量不足进入等待状态。当老板生产了包子之后,唤醒因为包子不足陷入等待的顾客线程,顾客来进行消费。当包子剩余数量超过20个时,为了避免产品堆积,表示老板的线程进入等待状态,等待顾客消费。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈