多线程wait方法报错?
我的问题:三个线程的ID分别是A,B,C;,每个线程将自己的ID值在屏幕上打印5遍,打印顺序是ABCABC。
我编写的代码:
package 并发编程.work2;public class Test {
private static volatile String CURRENT_THREAD = "A";
public static void main(String[] args) {
Thread t1 = new Thread(new PrintThreadName(), "A");
Thread t2 = new Thread(new PrintThreadName(), "B");
Thread t3 = new Thread(new PrintThreadName(), "C");
t1.start();
t2.start();
t3.start();
}
static class PrintThreadName implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
synchronized (CURRENT_THREAD) {
// 从A开始
while (!CURRENT_THREAD.equals(Thread.currentThread().getName())) {
try {
CURRENT_THREAD.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(CURRENT_THREAD);
// 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程
if (CURRENT_THREAD.equals("A")) {
CURRENT_THREAD = "B";
} else if (CURRENT_THREAD.equals("B")) {
CURRENT_THREAD = "C";
} else if (CURRENT_THREAD.equals("C")) {
CURRENT_THREAD = "A";
}
CURRENT_THREAD.notifyAll();
}
}
}
}
}
但是出现了错误
哪个地方出现了问题呢?
回答:
主要的问题是:
// 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程if (CURRENT_THREAD.equals("A")) {
CURRENT_THREAD = "B";
} else if (CURRENT_THREAD.equals("B")) {
CURRENT_THREAD = "C";
} else if (CURRENT_THREAD.equals("C")) {
CURRENT_THREAD = "A";
}
你使用一个volatile修饰的字符串CURRENT_THREAD来充当锁的角色
但是却在锁对象释放自己拥有的锁之前就把锁的引用给修改了
也就会出现 现在的锁对象其实已经被修改了(它是没有锁的 锁在之前的对象身上)
你还要让它释放锁 属于是强人所难了 所以会报错
这个错误产生的原因是某一线程在等待其他线程释放锁 但是突然要求它释放锁 它还在等呢怎么会有锁 所以就会抛出IllegalMonitorStateException
解决方法就是额外使用另一个锁对象来实现同步 不要在锁对象释放锁之前对它进行任何修改 可以参照楼上的方案
回答:
package 并发编程.work2;public class Test {
private static final Object lock = new Object();
private static volatile String CURRENT_THREAD = "A";
public static void main(String[] args) {
Thread t1 = new Thread(new PrintThreadName(), "A");
Thread t2 = new Thread(new PrintThreadName(), "B");
Thread t3 = new Thread(new PrintThreadName(), "C");
t1.start();
t2.start();
t3.start();
}
static class PrintThreadName implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
synchronized (lock) {
// 从A开始
while (!CURRENT_THREAD.equals(Thread.currentThread().getName())) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(CURRENT_THREAD);
// 线程打印完毕后,设置下一个要打印的线程标识,并唤醒其他线程
if (CURRENT_THREAD.equals("A")) {
CURRENT_THREAD = "B";
} else if (CURRENT_THREAD.equals("B")) {
CURRENT_THREAD = "C";
} else if (CURRENT_THREAD.equals("C")) {
CURRENT_THREAD = "A";
}
lock.notifyAll();
}
}
}
}
}
以上是 多线程wait方法报错? 的全部内容, 来源链接: utcz.com/p/945231.html