Java同步等待和通知方法

时间:2014-11-28 05:11:09

标签: java multithreading

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

问题: -

程序执行2个线程 - T1& T2同时但基于输出T1先运行,执行问题(第一)方法,打印问题,设置标志(true),运行notify()方法,执行问题(第二)方法&进入等待方法。现在T2开始并执行。

  1. 为什么在T1调用对象聊天的等待方法之前T2才会启动。
  2. 当第一次执行问题方法并调用notify()方法时,聊天对象上没有wait()(因为t2尚未启动)。所以,哪个线程监听这个通知方法。
  3. 我的代码:

    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!
    

3 个答案:

答案 0 :(得分:0)

  

为什么在T1调用对象聊天的等待方法之前T2不会启动?

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

  

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

没有。

答案 1 :(得分:0)

1。)为什么在T1调用对象聊天的等待方法之前T2不会启动?

实际上T2在此之前就开始了,但你没有注意到,因为你没有任何记录声明出现。将System.out置于T2的run方法中并运行您的程序几次。在T1调用wait方法之前你会看到T2开始。请记住,T2无法进入Chat对象的Answer方法,因为在最终调用wait()之前,T1会获取其锁定。

要记住的另一件事是无法保证线程的启动顺序。仅仅因为T1.start出现在T2.start之前,并不意味着T1将始终首先启动。线程调度程序做出了这个决定。

2.)当第一次执行问题方法并调用notify()方法时,聊天对象上没有wait()(因为t2尚未启动)。所以,哪个线程监听这个通知方法。

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

答案 2 :(得分:0)

  

为什么在T1调用Object的wait方法之前T2不会启动   聊天。

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

  

第一次执行问题方法时,notify()方法是   调用时,聊天对象上没有wait()(因为t2还没有   开始)。所以,哪个线程监听这个通知方法。

notify()第一次没有意义,synchronized方法必须完成全部。如前所述,在问题()完成/释放锁定(调用wait())之前,不执行answer()