结论:
1、高聚低合前提下,线程操作资源类
2、判断/干活/通知
3、多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if)
4、标记位
题目:
一个空调,两个人,一人关,一人开,交替进行。
package main.test;
/**
* @Auther: wdq
* @Date: 2020/4/19 15:53
* @Description:
*/
class AirConditioner {
private int number = 0;
public synchronized void increament() throws InterruptedException {
//wait
if(number==1){
this.wait();
}
//work
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//wait
if(number==0){
this.wait();
}
//work
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
}
public class threadWaitNotify {
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"B").start();
}
}
输出的结果为:
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
看起来结果很正确,但是如果新增两个人,变成四个人对空调开关,两人开,两人关,交替进行。
package main.test;
/**
* @Auther: wdq
* @Date: 2020/4/19 15:53
* @Description:
*/
class AirConditioner {
private int number = 0;
public synchronized void increament() throws InterruptedException {
//wait
if(number==1){
this.wait();
}
//work
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//wait
if(number==0){
this.wait();
}
//work
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
}
public class threadWaitNotify {
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"C").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"D").start();
}
}
部分结果为:
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
C 1
A 2
A 3
A 4
A 5
A 6
A 7
A 8
A 9
A 10
A 11
A 12
A 13
A 14
C 15
你会发现操作出错了。
这就是wait的虚假唤醒。
官网上的解释:
所有不能用if区判断而执行wait方法,要用while。
把上面的if改成while就行了。