【问题标题】:Java synchronization wait and notify methodsJava同步等待和通知方法
【发布时间】:2015-01-26 17:39:24
【问题描述】:

我是同步新手,并试图了解等待和通知的工作原理。

问题:-

程序同时执行 2 个线程 - T1 和 T2,但基于输出 T1 先运行,执行 question(first) 方法,打印问题,设置 flag(true),运行 notify() 方法,执行question(second) 方法 & 进入 wait 方法。现在 T2 启动并执行。

  1. 为什么直到 T1 调用 Object Chat 的 wait 方法后 T2 才开始。
  2. 第一次执行 question 方法并调用 notify() 方法时,聊天对象上没有 wait()(因为 t2 尚未开始)。那么,哪个线程监听这个通知方法。

我的代码:

package TestThread;

class Chat {
    boolean flag = false;

    public synchronized void Question(String msg) {

        System.out.println("Question method = " + flag);
        if (flag) {
            try {
                System.out.println("Question method wait start");
                wait();
                System.out.println("Question method wait finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(msg);
        flag = true;
        notify();
    }

    public synchronized void Answer(String msg) {
        System.out.println("Answer method = " + flag);
        if (!flag) {
            try {
                System.out.println("Answer method wait start");
                wait();
                System.out.println("Answer method wait finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(msg);
        flag = false;
        notify();
    }
}

class T1 implements Runnable {
    Chat m;
    String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" };

    public T1(Chat m1) {
        this.m = m1;
        new Thread(this, "Question").start();
    }

    public void run() {
        for (int i = 0; i < s1.length; i++) {
            m.Question(s1[i]);
        }
    }
}

class T2 implements Runnable {
    Chat m;
    String[] s2 = { "Hi", "I am good, what about you?", "Great!" };

    public T2(Chat m2) {
        this.m = m2;
        new Thread(this, "Answer").start();
    }

    public void run() {
        for (int i = 0; i < s2.length; i++) {
            m.Answer(s2[i]);
        }
    }
}

public class MultiThread {
    public static void main(String[] args) {
        Chat m = new Chat();
        new T1(m);
        new T2(m);            
    }
}

结果:-

Question method = false
Hi
Question method = true
Question method wait start
Answer method = true
Hi
Answer method = false
Answer method wait start
Question method wait finish
How are you ?
Question method = true
Question method wait start
Answer method wait finish
I am good, what about you?
Answer method = false
Answer method wait start
Question method wait finish
I am also doing fine!
Answer method wait finish
Great!

【问题讨论】:

  • 你可能想看这个,很容易理解:programcreek.com/2009/02/notify-and-wait-example
  • 尝试将您的new T1(m);new T2(m); 分别替换为new T1(m).start()new T2(m).start()。然后摆脱new Thread(this, "Question").start();new Thread(this, "Answer").start();。看看这是否使两个线程同时执行。

标签: java multithreading


【解决方案1】:

为什么T2直到T1调用Object的wait方法才启动 聊天。

你有一个相同的对象'm'并将它传递给不同的线程,并且有方法级别同步,所以当'调用'进入 question() 时,整个对象都会被锁定直到调用 wait() 因此 answer 方法将被阻止。

第一次执行 question 方法并且 notify() 方法是 调用,聊天对象上没有 wait()(因为 t2 还没有 开始)。那么,哪个线程监听这个通知方法。

notify() 首次没有意义,同步方法必须完成,仅此而已。如前所述, answer() 直到 question() 完成/释放锁(调用 wait())才会执行

【讨论】:

    【解决方案2】:

    为什么直到 T1 调用 Object Chat 的 wait 方法后 T2 才开始?

    你有一个竞争条件。两个线程中的任何一个都将首先执行。由于它们都共享一个 Chat 实例,其方法为 synchronized,因此一个会阻塞,直到另一个解锁 Chat 实例上的监视器。

    第一次执行question方法并且notify()方法是 调用,聊天对象上没有wait()(因为t2还没有 开始)。那么,哪个线程监听这个 notify 方法呢?

    没有。

    【讨论】:

      【解决方案3】:

      1.) 为什么直到 T1 调用 Object Chat 的 wait 方法后 T2 才开始?

      实际上 T2 在那之前就开始了,但您没有注意到,因为您没有任何日志语句要显示。在 T2 的 run 方法中放置一个 System.out 并运行您的程序几次。您将看到 T2 在 T1 调用等待方法之前启动。请记住,T2 无法进入 Chat 对象的 Answer 方法,因为它的锁是在最终调用 wait() 之前由 T1 获取的。

      要记住的另一件事是不能保证线程启动的顺序。仅仅因为 T1.start 出现在 T2.start 之前,并不意味着 T1 总是首先启动。线程调度程序做出该决定。

      2.)第一次执行 question 方法并调用 notify() 方法时,聊天对象上没有 wait()(因为 t2 尚未开始)。那么,哪个线程监听这个通知方法。

      --如果没有等待调用,则通知不会影响任何线程。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-16
        • 2011-10-24
        • 2011-02-07
        • 1970-01-01
        • 2015-11-12
        • 1970-01-01
        • 2019-12-23
        相关资源
        最近更新 更多