我正在学习OCJP,现在在“线程”一章中,我对等待和通知方法有一些疑问。我想我了解这里发生了什么,但是我只是想确保自己走对了路。我以下面的代码为例:
package threads;
public class Main {
static Object lock = new Object();
public static void main(String[] args) {
new Main().new FirstThread().start();
new Main().new SecondThread().start();
}
class FirstThread extends Thread {
public void run() {
synchronized (lock) {
lock.notify();
System.out.println("I've entered in FirstThread");
}
}
}
class SecondThread extends Thread {
public void run() {
synchronized (lock) {
try {
lock.wait();
System.out.println("I'm in the second thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
在此示例中,控制台输出为I've entered in FirstThread
,因为第一个线程启动,调用notify()方法,然后第二个线程启动,调用wait()方法,并且不打印字符串“我在第二个线程中” 。
接下来的情况是,我逆转的位置new Main().new FirstThread().start();
和new Main().new SecondThread().start();
输出
I've entered in FirstThread
I'm in the second thread
因为第二个线程启动了,所以调用了wait()方法,然后第一个线程启动了,调用了notify()方法,控制台打印出来I've entered in FirstThread
,释放等待,并在控制台中打印I'm in the second thread
出来。
发生这种情况是因为计算机速度如此之快并且线程按顺序运行吗?从理论上讲,我认为可以先调用第二个start()方法。
我的最后一个问题是,为什么锁对象必须是静态的,因为如果删除静态修饰符,输出将始终是I've entered in FirstThread
?
我知道在加载类时会在JVM中加载静态字段,但是我无法理解锁对象的逻辑。
线程是按顺序启动的,并且理论上讲线程1将在线程2之前执行,尽管不能保证(尽管在这种简单情况下,可以肯定它是一致的,因为没有实际的或模拟的延误延迟)。
这就是为什么在线程2刚刚启动之前,它有机会等待随后被线程1通知的锁,而不必永远等待已经被通知一次的锁(因此,不进行打印)。
在static
锁Object
:要绑定你的[First/Second]Thread
嵌套类实例的Main
,所以锁必须是常见的两种,如果你希望他们在同一个锁进行同步。
如果它是一个实例对象,则您的线程将访问并在另一个锁上同步,因为您的new Main()...
惯用语将获得的两个实例,Main
随后获得的两个实例lock
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句