为了账号安全,请及时绑定邮箱和手机立即绑定

使用wait()和notify()进行同步

使用wait()和notify()进行同步

喵喔喔 2021-05-11 17:22:53
我需要使用3个不同的线程来打印以下模式:线程1打印“ I”线程2打印“ LOVE”线程3打印“ EARTH”I LOVE EARTHI LOVE EARTHI 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)                {   有人可以解释如何解决这个问题吗?
查看完整描述

2 回答

?
慕运维8079593

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();


    }


}



查看完整回答
反对 回复 2021-05-19
?
沧海一幻觉

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语句。


查看完整回答
反对 回复 2021-05-19
  • 2 回答
  • 0 关注
  • 135 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信