等待和通知
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