假死
“假死”的现象就是线程进入WAITING等待状态。如果全部线程进入WAITING状态,则程序就不再执行任何业务功能了,整个项目呈现停止状态。
例子
(1)ValueObject 类
public class ValueObject {
public static String value = "";
}
(2)P类(生产者)
- 当生产者进行生产的时候,是实心的★,消费者消费完后,会变成空心的☆
//生产者
public class P {
private String lock;
public P(String lock) {
this.lock = lock;
}
public void setValue() {
synchronized (lock) {
try {
while (!ValueObject.value.equals("")) {
System.out.println(Thread.currentThread().getName() + " WAITING了");
lock.wait();
}
System.out.println(Thread.currentThread().getName() + " RUNNABLE了 ★");
String value = System.currentTimeMillis() + "_" + System.nanoTime();
ValueObject.value = value;
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(3)C类(消费者)
//消费者
public class C {
private String lock;
public C(String lock) {
this.lock = lock;
}
public void getValue() {
synchronized (lock) {
try {
while (ValueObject.value.equals("")) {
System.out.println(Thread.currentThread().getName() + " WAITING了");
lock.wait();
}
System.out.println(Thread.currentThread().getName() + " RUNNABLE了 ☆");
ValueObject.value = "";
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(4)ThreadC(消费者线程)
public class ThreadC extends Thread {
private C c;
public ThreadC(C c) {
this.c = c;
}
@Override
public void run() {
super.run();
while (true) {
c.getValue();
}
}
}
(5)ThreadP(生产者线程)
public class ThreadP extends Thread {
private P p;
public ThreadP(P p) {
this.p = p;
}
@Override
public void run() {
super.run();
while (true) {
p.setValue();
}
}
}
(6)Run类
public class Run {
public static void main(String[] args) {
String lock = new String("");
P p = new P(lock);
C c = new C(lock);
ThreadP[] pThread = new ThreadP[2];
ThreadC[] cThread = new ThreadC[2];
for (int i = 0; i < 2; i++) {
pThread[i] = new ThreadP(p);
pThread[i].setName("生产者" + (i + 1));
cThread[i] = new ThreadC(c);
cThread[i].setName("消费者" + (i + 1));
pThread[i].start();
cThread[i].start();
}
}
}
运行结果
-
运行结果很长,这里截取最后出问题的一部分。
-
可以看出,四个线程都进入了WAITING等待状态。
分析
原因是因为notify
唤醒的不一定是异类,有可能是同类。比如生产者唤醒生产者、消费者唤醒消费者。如果按照这种情况积少成多,就会导致所有线程不能运行下去。
解决方法
将P.java和C.java文件中的notify()
改成notifyAll()
方法,直接同时通知同类线程和异类线程。