详细分析java线程wait和notify

网友投稿 185 2023-07-30


详细分析java线程wait和notify

wait()和notify()是直接隶属于Object类,也就是说,所有对象都拥有这一对方法。初看起来这十分 不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用任意对象的notify()方法则导致因调用该对象的wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

其次,wait()和notify()可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在 synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以 释放。因此,方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的加锁对象就是调用这些方法的对象。若不满足这一条 件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。

wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作 一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则 相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间 通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。

关于 wait() 和 notify() 方法最后再说明两点:

    第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。

    第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调 用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。

相关wait和notify使用demo:

/**

*

* 子线程循环10次,接着主线程循环100次,接着有回到子线程循环10次,

* 接着再回到主线程循环100次,如此执行50次

*

* @author ketqi

*/

public class WaitNotifyDemo {

public static void main(String[] args) {

final Business business = new Business();

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 1; i <= 50; i++) {

business.sub(i);

}

}

}).start();

for (int i = 1; i <= 50; i++) {

business.main(i);

}

}

}

class Business {

private boolean isMainThread = true;

public synchronized void sub(int i) {

while (!isMainThread) {

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

for (int j = 1; j <= 10; j++) {

System.out.println("sub thread sequence of " + j + ",loop of " + i);

}

isMainThread = false;

this.notify();

}

public synchronized void main(int i) {

while (isMainThread) {

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

for (int j = 1; j <= 100; j++) {

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

isMainThread = true;

this.notify();

}

}

以上就是本文的全部内容,希望大家可以喜欢。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:学习在一台新电脑上配置JAVA开发环境
下一篇:再谈java回调函数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~