线程的同步通信是一种避免死锁,让线程在进入阻塞状态时尽量释放其锁定的资源,以便为其他的线程提供运行的机会的有效解决措施。
所谓的的同步通信,就和线程的同步差不多,因为二者在操作的资源上都是那种临界资源,只不过线程的同步和线程的同步通信二者的执行动作(即 run()方法中存放的线程处理代码)不同。
wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的线程就有机会访问该对象。
notify():唤醒调用wait()方法后被阻塞的线程。每次运行该方法只能唤醒一个线程。
notifyAll():唤醒所有调用wait()方法被阻塞的线程。
}
class Input implements Runnable{
}
class Output implements Runnable{
}
publicclass TestInfor {
}
这样就实现了线程的同步通信
再看一实例:
生产者-消费者问题是多线程同步处理的典型问题
原理:有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品。并且生产者和消费者生产出产品后才通知消费者消费,否则,消费者只能等待生产者生产出来后在消费。
我们来看一个例子的出现的几种不同状况,从而也加深一下我们对于同步通信构架来历的理解。
class Res{
}
class Input implements Runnable{
}
class Output implements Runnable{
}
publicclass TestInfor {
}
最后的输出结果为:
张三...男
李四...男
张三...女
李四...女
李四...女
张三...女
李四...男
看这种结果我们知道张三和李四的性别显然不是我们所期待的这种性别的点到输出,是由于线程的不稳定性造成的,某一线程在它的时间权限内不停的改变着临界资源的值,但是当某一刻权限失去时它并不是改变了所有的值而是一部分,这就是出现此类问题的原因。
如:
即只需要将两个runf()方法中加上同步代码块就OK了
publicvoid run() {
张三...男
张三...男
张三...男
李四...女
李四...女
李四...女
李四...女
可是,这也不是我们所预期的那种效果,我们希望张三和李四交替着出现,可这又怎么实现呢?
其实,这就用到我们今天将到线程间的同步通信。
我们只需在两个run()方法中合适的地方添加上相应的wait()和notify()方法即可
在这里,我们
publicvoid run() {
张三...男
李四...女
张三...男
李四...女
张三...男
李四...女
张三...男
李四...女
...
最终通过线程间的同步通信达到了按时交替操作的效果。这样也能避免因缓冲区已满而生产者却不停止产品的生产,也不能因缓冲区空消费者却继续消费了,这二者只能同时进行。