Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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
在if条件内调用Java notify()_Java_Multithreading_Wait_Notify - Fatal编程技术网

在if条件内调用Java notify()

在if条件内调用Java notify(),java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我刚刚编写了一个简单的java示例,以熟悉wait和notify方法的概念 其思想是,当调用notify()时,主线程将打印总和 MyThread类 public class MyThread extends Thread { public int times = 0; @Override public void run() { synchronized (this) { try { for (i

我刚刚编写了一个简单的java示例,以熟悉wait和notify方法的概念

其思想是,当调用
notify()
时,主线程将打印总和

MyThread类

public class MyThread extends Thread {
    public int times = 0;

    @Override
    public void run() {

        synchronized (this) {
            try {
                for (int i = 0; i < 10; i++) {
                    times += 1;
                    Thread.sleep(500);
                    if (i == 5) {
                        this.notify();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {

    public static void main(String[] args) {

        MyThread t = new MyThread();
        synchronized (t) {
            t.start();
            try {
                t.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(t.times);
        }
    }
}
预期结果

public class MyThread extends Thread {
    public int times = 0;

    @Override
    public void run() {

        synchronized (this) {
            try {
                for (int i = 0; i < 10; i++) {
                    times += 1;
                    Thread.sleep(500);
                    if (i == 5) {
                        this.notify();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {

    public static void main(String[] args) {

        MyThread t = new MyThread();
        synchronized (t) {
            t.start();
            try {
                t.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(t.times);
        }
    }
}
5,但我得到了10

嗯,我的想法是,当调用
notify()
时,主线程将唤醒并执行
System.out.println(t.times)
,它应该给出5。然后,
run()
将继续运行,直到完成for循环,该循环将times的值更新为10


非常感谢您的帮助。

同步块意味着相互排斥。在任何给定时刻,只允许一个线程持有锁并在同步块中执行代码。这条规则适用于由同一把锁保护的所有区块

在您的例子中,有两个这样的块使用同一个锁,因此允许主线程或
MyThread
在这两个块中执行代码,另一个线程必须等待。因此,这里有以下场景:

  • 主线程获取锁
  • 主线程启动第二个线程
  • 第二个线程命中同步块,但无法进入,因为锁被主线程持有
  • 主线程调用
    wait()
    。此调用将释放锁,并将主线程置于
    等待
    状态
  • 第二个线程现在可以获取锁并进入同步块
  • 第二个线程计数为5,并调用
    notify()
    。这个调用并没有释放锁,它只是通知主线程它可以在重新获得锁后立即进行
  • 主线程会唤醒,但它无法前进,因为它无法重新获取锁(它仍被第二个线程保持)。请记住,在由同一个锁保护的同步块中,不能同时有两个线程处于活动状态,现在,第二个线程仍然处于活动状态,因此主线程必须继续等待
  • 第二个线程继续计数,将
    时间设置为10,并最终离开同步块,释放锁
  • 主线程重新获得锁,现在可以进入
    println
    。但此时,
    的次数已经是10次了
  • 使用
    join()

    如果希望主线程在第二个线程到达
    5
    时继续执行,则需要获取锁并在该事件发生后立即释放锁:

    public class MyThread extends Thread {
        public volatile int times = 0;
    
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    times += 1;
                    Thread.sleep(500);
                    if (i == 5) {
                        synchronized(this) {
                            this.notify();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    公共类MyThread扩展线程{
    公共不稳定整数倍=0;
    @凌驾
    公开募捐{
    试一试{
    对于(int i=0;i<10;i++){
    次数+=1;
    睡眠(500);
    如果(i==5){
    已同步(此){
    this.notify();
    }
    }
    }
    }
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    
    不要忘记将
    时间设置为volatile,否则JVM不能保证在主线程中看到它的实际值


    您还应该了解,这种方法不能保证主线程打印5。可能会出现这样的情况:当第二个线程到达
    println
    调用时,它会进行一次、两次甚至更多的迭代,并且您会看到大于5次的迭代(尽管这非常不幸,因为每次迭代都会调用
    sleep()
    ).

    notify
    不会释放锁。请您进一步说明这一点。线程的可能副本不会离开同步块。所以main将无法继续运行,尽管等待可能会返回。谢谢大家。理解。嗯,在这种情况下,我可以用join()来代替。它工作起来很有魅力。谢谢你,安德鲁。非常感谢