关于wait及notify、notifyAll方法的总结:
- 当调用wait时候,首先需要确保调用了wait方法的线程已经持有了对象的锁。
- 当调用了wait后,该线程会释放掉对象的锁,然后进入到等待状态(wait set)。
- 当线程调用了wait方法后进入等待状态时,它就可以等待其他线程调用相同对象的notify或者notifyAll方法来使得自己被唤醒。
- 一旦这个线程被其他线程唤醒后, 该线程就会同其他线程一同竞争这个对象的锁(公平竞争),只有当该线程获取到了这个对象的锁后,线程才会继续向下进行。
- 调用wait方法的片段需要放在一个synchronized块或者是synchronized方法中,这样才可以确保线程在调用wait方法前已经获取到了对象的锁。
6.当调用对象的notify方法时,会随机唤醒等待集合(wait set)中的任意一个线程,当某个线程被唤醒后,它就会与其他线程一同竞争对象的锁。
7.当调用notifyAll方法时,它就会唤醒该对象等待集合(wait set)中的线程,这些线程被唤醒后又开始竞争对象的锁。
8.在某一时刻只有唯一一个线程可以拥有对象的锁。
编写一个多线程程序,实现这样一个目标:(多线程通信)
- 存在一个对象,该对象有一个int类型的成员变量counter 对象的初始值为0;
- 创建两个线程,其中一个线程对该对象的counter增加1,另一个减少1
- 输出该对象的counter每次变化的值。
- 最终输出结果是10101010101...
IncrAndDecr.java
package com.compass.spring_lecture.thread;
public class IncrAndDecr {
int counter;
public synchronized void increment() {
while (counter == 1) {
try {
wait();//通常wait必须放在while loop中 防止伪唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
counter++;
System.out.print(counter);
notify();
}
public synchronized void decrement() {
while (counter == 0) {
try {
wait();//通常wait必须放在while loop中 防止伪唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
counter--;
System.out.print(counter);
notify();
}
}
IncrThread .java
package com.compass.spring_lecture.thread;
public class IncrThread extends Thread {
private IncrAndDecr incrAndDecr;
public IncrThread(IncrAndDecr incrAndDecr) {
this.incrAndDecr = incrAndDecr;
}
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
incrAndDecr.increment();
}
}
}
DecrThread.java
package com.compass.spring_lecture.thread;
public class DecrThread extends Thread {
private IncrAndDecr incrAndDecr;
public DecrThread(IncrAndDecr incrAndDecr) {
this.incrAndDecr = incrAndDecr;
}
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
incrAndDecr.decrement();
}
}
}
MyTest2.java
package com.compass.spring_lecture.thread;
public class MyTest2 {
public static void main(String[] args) {
IncrAndDecr incrAndDecr = new IncrAndDecr();
IncrThread incrThread = new IncrThread(incrAndDecr);
DecrThread decrThread = new DecrThread(incrAndDecr);
incrThread.start();
decrThread.start();
}
}
output:101010101010101010101010101010101010101010101010101010101010
网友评论