在 if 条件内调用 Java 的 notify() 方法

6 浏览
0 Comments

在 if 条件内调用 Java 的 notify() 方法

我刚刚写了一个简单的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();
            }
        }
    }
}

Main类

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。

非常感谢您的帮助。

0
0 Comments

问题的原因是,当在一个if条件语句中调用Java的notify()方法时,会导致主线程无法继续执行。

解决方法是,在第二个线程达到条件时,立即获取锁并释放锁,以便让主线程继续执行。具体代码如下:

public class MyThread extends Thread {
    public volatile int times = 0;
    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();
        }
    }
}

需要注意的是,需要将times变量声明为volatile,以确保在主线程中能够看到其实际值。

然而,这种方法并不能保证主线程打印出5。可能会出现这样的情况,当主线程执行到println方法时,第二个线程已经进行了一两次甚至更多次迭代,因此打印出的值可能大于5。不过由于每次迭代都有sleep方法的调用,这种情况发生的概率很低。

总之,通过在if条件语句中调用notify()方法,并在第二个线程中释放锁,可以让主线程继续执行。不过需要注意的是,这种方法无法保证主线程打印出指定的数值。

0