Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 调用wait和notify的两个线程_Java_Multithreading_Wait - Fatal编程技术网

Java 调用wait和notify的两个线程

Java 调用wait和notify的两个线程,java,multithreading,wait,Java,Multithreading,Wait,我编写的代码没有像我预期的那样工作 static Integer sync = 1; static void m() throws Exception { synchronized (sync) { System.err.println("First"); sync.notify(); sync.wait(1000L); System.err.println("Second"

我编写的代码没有像我预期的那样工作

static Integer sync = 1;

    static void m() throws Exception {
        synchronized (sync) {
            System.err.println("First");
            sync.notify();
            sync.wait(1000L);
            System.err.println("Second");
            System.err.println("Third");
        }
    }

    public static void main(String[] args) throws Exception {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    m();
                } catch (Exception ex) {
                    Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        Runnable t = new Runnable() {
            @Override
            public void run() {
                try {
                    m();
                } catch (Exception ex) {
                    Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        Thread th1 = new Thread(r);
        Thread th2 = new Thread(t);
        th1.run();
        th2.run();
   }
我们有两个线程执行
m()
的syncjronized语句。当第一个线程执行一个线程并遇到
wait()
时,它将被添加到等待集中。在此之后,第二个线程开始执行synchronized语句,并执行notify()。因为输出必须是

First
First
....
但实际上是这样

First
Second
Third
First
Second
Third

为什么?

首先,您的程序没有创建任何线程。必须调用th1.start()和th2.start()来创建线程

t、 start()是库提供的方法,当您想要启动线程时,可以调用代码。run()是为库提供的在新线程中调用的方法。run()方法定义线程将执行的操作。在我看来,run()确实是一个误导性的名字

其次,notify()和wait()不要做你认为他们会做的事情。特别是,如果当前没有其他线程处于sync.wait()状态,sync.notify()将不会执行任何操作

使用notify()和wait()的正确方法是,一个线程执行以下操作:

synchronized(lock) {
    while (! someCondition()) {
         lock.wait()
    }
    doSomethingThatRequiresSomeConditionToBeTrue();
}
另一个线程执行此操作

synchronized(lock) {
    doSomethingThatMakesSomeConditionTrue();
    lock.notify();
}

使用此模式时,除了从同步(锁定)块内部更改someCondition()的结果外,任何线程都不应更改该结果。

首先,您的程序不会创建任何线程。必须调用th1.start()和th2.start()来创建线程

t、 start()是库提供的方法,当您想要启动线程时,可以调用代码。run()是为库提供的在新线程中调用的方法。run()方法定义线程将执行的操作。在我看来,run()确实是一个误导性的名字

其次,notify()和wait()不要做你认为他们会做的事情。特别是,如果当前没有其他线程处于sync.wait()状态,sync.notify()将不会执行任何操作

使用notify()和wait()的正确方法是,一个线程执行以下操作:

synchronized(lock) {
    while (! someCondition()) {
         lock.wait()
    }
    doSomethingThatRequiresSomeConditionToBeTrue();
}
另一个线程执行此操作

synchronized(lock) {
    doSomethingThatMakesSomeConditionTrue();
    lock.notify();
}

使用此模式时,除了从同步(锁定)块内部更改someCondition()的结果外,任何线程都不应更改该结果。

首先,要实际创建新线程,请使用

th1.start() th2.start()

代替run(),它只是线程对象上的常规方法调用

其次,第二个线程“th2”可能在1000毫秒之前没有开始运行,因此第一个线程完成等待(1000)并执行剩余的代码行

如果您希望这样输出:

first
first
second
third
second
third
然后删除wait()的时间间隔,这将使线程等待通知。 例如:


首先,要实际创建新线程,请使用

th1.start() th2.start()

代替run(),它只是线程对象上的常规方法调用

其次,第二个线程“th2”可能在1000毫秒之前没有开始运行,因此第一个线程完成等待(1000)并执行剩余的代码行

如果您希望这样输出:

first
first
second
third
second
third
然后删除wait()的时间间隔,这将使线程等待通知。 例如:

  • 使用
    .start()
    而不是
    run()
    将可运行项添加到队列中,而不是立即运行它们

  • 表示带超时的
    等待
    等待此对象上的任何
    通知
    超时。在您的情况下,当一个接一个地执行可运行文件时,它会:

    • r:首先
    • r:等待1000毫秒并尝试获取锁
    • r:它已经有了锁定对象的访问权限(正是这个代码被锁定了),所以继续吗
    • r:第二
    • r:第三
    • t:首先,等等
  • 另外,调用
    run()
    而不设置timeout将导致t的等待出现死锁,因为它已经有了对象,但不会被通知

    希望这有帮助

  • 使用
    .start()
    而不是
    run()
    将可运行项添加到队列中,而不是立即运行它们

  • 表示带超时的
    等待
    等待此对象上的任何
    通知
    超时。在您的情况下,当一个接一个地执行可运行文件时,它会:

    • r:首先
    • r:等待1000毫秒并尝试获取锁
    • r:它已经有了锁定对象的访问权限(正是这个代码被锁定了),所以继续吗
    • r:第二
    • r:第三
    • t:首先,等等
  • 另外,调用
    run()
    而不设置timeout将导致t的等待出现死锁,因为它已经有了对象,但不会被通知


    希望这有帮助。

    首先,您调用的是
    Thread.run()
    ,而不是
    Thread.start()
    ,因此您的代码实际上是单线程的。如果您在
    sync
    @JeanLogeart上进行同步,请不要期望首先看到它。您能解释一下原因吗?我真的不明白(尽管我已经从JLS中读到了相应的子句)。不要在
    Integer
    1对象上同步。它们被有效地隔离,因此执行相同操作的无关代码片段将在同一对象上同步。使用
    new Object()
    。首先,您调用的是
    Thread.run()
    ,而不是
    Thread.start()
    ,因此您的代码实际上是单线程的。如果您在
    sync
    @JeanLogeart上进行同步,请不要期望首先看到?我真的不明白(尽管我已经从JLS中读到了相应的子句)。不要在
    Integer
    1对象上同步。它们被有效地隔离,因此执行相同操作的无关代码片段将在同一对象上同步。改用
    newobject()