Java线程---------等待和通知(生产者和消费者实例)

等待和通知

java.lang.Object类提供了一套等待/通知 的API。

由以下组成:

`void wait()` :导致当前线程一直处于等待,直到另外的线程调用这个对象的notify()或者notifyAll()方法,又或者一直等待其他的线程中当前等待的线程。

`void wait(long timeout)`

`void wait(long timeout,int nanos)`

`void notify()`: 唤醒正站在等待该对象监听器的单条线程

`void notifyAll()`: 唤醒正站在等待该对象监听器的全部线程

对象的wait()方法调用时,线程会放弃对象关联的监听器的所有权

关于调用wait()方法

这里需要演示下

synchronized(obj){	while(<condition soed not hold)	obj.wait();}

> 有个提醒,就是绝对不要在循环外面调用wait()方法。这个循环会在wait()调用前后进行条件测试。调用wait()的前后会影响线程。notify()方法先于wait()方法调用,等待中的线程就不太可能醒来 。而调用wait()之后重新测试条件,保证了安全性。如果没有重新测试,并且线程已经从wait()中醒来,同时条件有没有满足,这个线程可能会继续破坏锁所维护的一致性。 --Java线程与并发实战

那什么时候使用notify()和notifyAll()? 在应用程序中,仅有两条线程并且某条线程偶尔等待,需要被另一条线程通知的时候,才使用notify()方法,否则使用notifyAll()方法。

这里有个典型的例子 -----生产者和消费者(能看懂基本明白等待和通知还有同步的原理)

package thread;

public class PC {

	public static void main(String[] args) {
		Shared s= new Shared();
		new Producer(s).start();
		new Consumer(s).start();
	}

}
class Shared {
	private char c;

	private volatile boolean writeable = true;

	synchronized void setSharedChar(char c) {
		while (!writeable)
			try {
				wait();
			} catch (InterruptedException ie) {
			}
		this.c = c;
		writeable = false;
		notify();
	}

	synchronized char getSharedChar() {
		while (writeable)
			try {
				wait();
			} catch (InterruptedException ie) {
			}
		writeable = true;
		notify();
		return c;
	}
}
class Producer extends Thread {
	private final Shared s;

	Producer(Shared s) {
		this.s = s;
	}

	@Override
	public void run() {
		for (char ch = 'A'; ch <='Z'; ch++) {
			
				s.setSharedChar(ch);
				System.out.println(ch + " produced by producer.");
			
		}
	}
}
class Consumer extends Thread {
	private final Shared s;

	Consumer(Shared s) {
		this.s = s;
	}

	public void run() {
		char ch;
		do {
		
				ch = s.getSharedChar();
				System.out.println(ch + " Consumed by consumer.");
			
		} while (ch != 'Z');
	}
}

其结果是:

A produced by producer.
A Consumed by consumer.
B produced by producer.
B Consumed by consumer.
C produced by producer.
C Consumed by consumer.
D produced by producer.
D Consumed by consumer.
E produced by producer.
E Consumed by consumer.

其中的线程 F是叛徒,他先消费了再生产。

F Consumed by consumer.
F produced by producer.
G produced by producer.
G Consumed by consumer.
H produced by producer.
H Consumed by consumer.
I produced by producer.
I Consumed by consumer.
J produced by producer.
J Consumed by consumer.
K produced by producer.
K Consumed by consumer.
L produced by producer.
M produced by producer.
L Consumed by consumer.
M Consumed by consumer.
N produced by producer.
N Consumed by consumer.
O produced by producer.
P produced by producer.
O Consumed by consumer.
P Consumed by consumer.
Q produced by producer.
R produced by producer.
Q Consumed by consumer.
R Consumed by consumer.
S produced by producer.
T produced by producer.
S Consumed by consumer.
T Consumed by consumer.
U produced by producer.
V produced by producer.
U Consumed by consumer.
V Consumed by consumer.
W Consumed by consumer.
W produced by producer.
X produced by producer.
X Consumed by consumer.
Y produced by producer.
Y Consumed by consumer.
Z Consumed by consumer.
Z produced by producer.

有叛徒,不代表这线程不是同步的。其实是其中setSharedChar()之后的输出和getSharedChar()之后的输出没有同步的结果。应该是writeable的值设为true和false在线程中陷入等待时的造成的。那么解决办法是在Producer和Consumer中的setSharedChar()、getSharedChar()中加一个synchronized 同步块。

版权声明:本文为博主原创文章,未经博主允许不得转载。https://mp.csdn.net/postedit/80973382

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值