我需要使用3个不同的线程来打印以下图案:
线程1打印“ I”
线程2打印“ LOVE”
线程3打印“ EARTH”
I LOVE EARTH
I LOVE EARTH
I LOVE EARTH
使用wait()和notify()方法。 我从下面的代码开始,但是似乎它们只打印一次,因为它们都在每个循环的第一次迭代结束时等待。
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() {
if(word.equals("I"))
{
synchronized(m)
{
for(int i=1;i<=2;i++) {
if(word.equals("I")) {
System.out.println("I ");
word="LOVE";
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
m.notify();
}
}
}
}
};
Runnable b = new Runnable() {
public void run() {
if(word.equals("LOVE"))
{
synchronized(m)
{
for(int j=1;j<=2;j++) {
if(word.equals("LOVE")) {
System.out.println("LOVE ");
word="WORLD";
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.notify();
}
}
}
}
}
};
Runnable c = new Runnable() {
public void run() {
if(word.equals("WORLD"))
{
synchronized(m)
{
for(int k=1;k<=2;k++) {
System.out.println("WORLD ");
word="I";
try {
m.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.notify();
}
}
}
}
};
new Thread(a).start();
Thread.sleep(100);
new Thread(b).start();
Thread.sleep(100);
new Thread(c).start();
}
}
有人可以解释如何解决这个问题吗?
答案 0 :(得分:1)
我已修复您的代码。您已将“ 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();
}
}
答案 1 :(得分:1)
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语句。