2 回答
![?](http://img1.sycdn.imooc.com/533e4bd900011a1d02000200-100-100.jpg)
TA贡献1876条经验 获得超5个赞
我已经修复了您的代码。您已将“ m.notify()”放在“ m.wait()”之后,因此它们都互相等待。我在“ m.wait()”之前轻轻移动了它,并将for循环转换为无尽的while循环,以使线程永远运行。
更新1
我已经更新了代码,以便线程将文本写入3次。
public class MultiThreading_2 {
static volatile boolean flag = false;
static volatile String word = "I";
public static void main(String[] args) throws InterruptedException {
MultiThreading_2 m = new MultiThreading_2();
Runnable a = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (m) {
if (word.equals("I")) {
System.out.print("I ");
word = "LOVE";
m.notify();
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
i--;
}
}
}
}
};
Runnable b = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (m) {
if (word.equals("LOVE")) {
System.out.print("LOVE ");
word = "WORLD";
m.notify();
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
i--;
}
}
}
}
};
Runnable c = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (m) {
if (word.equals("WORLD")) {
System.out.println("WORLD ");
word = "I";
m.notify();
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
i--;
}
}
}
}
};
new Thread(a).start();
Thread.sleep(100);
new Thread(b).start();
Thread.sleep(100);
new Thread(c).start();
}
}
![?](http://img1.sycdn.imooc.com/5458477f0001cabd02200220-100-100.jpg)
TA贡献1824条经验 获得超5个赞
Object.notify()选择一个随机线程唤醒。由于两次启动之间的睡眠,您的代码只能工作一次,因此您可以人为地确保预期的执行顺序。
您应该使用notifyAll(),唤醒所有线程,因此,线程应该wait()循环循环,直到轮到为止:
Runnable a = new Runnable() {
public void run() {
synchronized (m) {
for (int i = 1; i <= 2; i++) {
while(!word.equals("I"))
try{
m.wait();
}
catch(InterruptedException ie){
ie.printStackTrace();
}
System.out.print("I ");
word = "LOVE";
m.notifyAll();
}
}
}
};
Runnable b = new Runnable() {
public void run() {
synchronized (m) {
for (int i = 1; i <= 2; i++) {
while(!word.equals("LOVE"))
try{
m.wait();
}
catch(InterruptedException ie){
ie.printStackTrace();
}
System.out.print("LOVE ");
word = "WORLD";
m.notifyAll();
}
}
}
};
Runnable c = new Runnable() {
public void run() {
synchronized (m) {
for (int i = 1; i <= 2; i++) {
while(!word.equals("WORLD"))
try{
m.wait();
}
catch(InterruptedException ie){
ie.printStackTrace();
}
System.out.println("WORLD ");
word = "I";
m.notifyAll();
}
}
}
};
new Thread(a).start();
new Thread(b).start();
new Thread(c).start();
在if从一开始就已经被删除,在真正的并发执行难保有在预期值word。然后,其中一个线程抓住该锁,检查是否word是自己的那个线程,或者开始等待,或者打印其文本和步骤word以进入下一阶段,从而唤醒其他线程(两个线程都带有notifyAll())。然后它要么退出,要么继续wait()再次。这是重要的部分:我想尽可能少地修改您的代码,以便所有事情都在同步块内发生,这意味着线程仅在其他两个正在等待或完成时才可以运行。对于此锁步,它可以工作,但通常而言,同步块应该位于for循环内,可能是两个单独的块,一个围绕equals-wait循环,另一个围绕set + notifyAll语句。
添加回答
举报