线程obj.wait()和obj.notify()详解.

本文详细介绍了Java中wait()和notify()方法的使用方法及注意事项,通过实例演示了如何利用这两种方法实现线程间的同步通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wait()和notify()同属于Object里面的成员方法。


Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。


从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。

相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。


ps:线程的同步通信和互斥其实就是把用到相同程序块的地方排序并按照执行顺序的执行。


下面的程序运用到了wait()和notify()。线程实现同步通信编程,题目:子进程先执行10次,然后主进程执行100次,并且循环50次。

public class TraditionalThreadCommunication {


	/**
	 * @param args
	 */
	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 {       
/*  实现子进程执行10次和主进程执行100次的方法,并且封装在Business类里面,增加了bShouldSub,
判断是否先执行子进程,如果不是,暂停主进程(wait()),并且转到子进程(notify())执行10次,
接着执行主进程,循环下去。  */

	  private boolean bShouldSub = true;
	  public synchronized void sub(int i){
		  while(!bShouldSub){
			  try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		  }
			for(int j=1;j<=10;j++){
				System.out.println("sub thread sequence of " + j + ",loop of " + i);
			}
		  bShouldSub = false;
		  this.notify();
	  }
	  
	  public synchronized void main(int i){
		  	while(bShouldSub){
		  		try {
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		  	}
			for(int j=1;j<=100;j++){
				System.out.println("main thread sequence of " + j + ",loop of " + i);
			}
			bShouldSub = true;
			this.notify();
	  }
  }

还是很少用到了wait()和notify()函数,但是它们是相对的,所以在实际运用中比较好把握。


<think>好的,用户想了解Java中LockSupportObject.wait的区别、关系以及使用场景。首先,我需要回忆这两个机制的基本概念。LockSupport是JUC包中的工具类,提供parkunpark方法用于线程阻塞唤醒。而Object.waitnotifyObject类的方法,用于传统的线程间通信,必须在同步块中使用。 接下来,要比较它们的区别。首先想到的是使用方式的不同:Object.wait需要在synchronized块内获取对象锁,否则会抛出IllegalMonitorStateException,而LockSupport.park不需要,直接调用即可。然后是唤醒机制,wait需要notifynotifyAll来唤醒,而LockSupport.unpark可以指定线程提前唤醒,或者之后解除阻塞。还有许可证机制,LockSupport的unpark会给线程一个许可证,即使之后调用park也不会阻塞,这点wait不同,后者没有这种累积效应。 再者,需要考虑它们的使用场景。Object.wait适用于经典的等待-通知模式,比如生产者消费者问题。而LockSupport更适合更底层的线程控制,比如在AQS(AbstractQueuedSynchronizer)中的使用,或者需要更灵活的线程挂起恢复的场景。 还要提到中断处理。两者对中断的响应不同,park会立即返回并清除中断状态,而wait被中断时会抛出InterruptedException,需要捕获处理。 另外,需要引用提供的参考资料来支持这些观点。例如,引用[4]指出wait必须在synchronized中使用,否则会抛出异常。引用[5]提到三种让线程休眠的方法,包括LockSupport.park。引用[3][4]讨论了LockSupport与wait的区别,比如许可证机制同步要求。 最后,应该总结它们的适用情况,帮助用户根据具体需求选择合适的方法。可能用户在实际开发中遇到了线程同步的问题,或者在阅读源码时看到这两种方法的使用,需要理解其差异。需要确保回答结构清晰,分点说明,并结合示例代码帮助理解。</think>### Java中LockSupport与Object.wait的关系及区别分析 #### 一、核心关系 两者均为Java线程同步机制,但属于不同层级的解决方案: - $Object.wait()$ 是Java基础API,需要配合$synchronized$关键字使用[^4] - $LockSupport$ 是JUC包中的高级工具,提供更底层的线程控制能力[^3] #### 二、主要差异对比(表格形式) | 特性 | LockSupport | Object.wait/notify | |---------------------|----------------------------|----------------------------| | 同步机制 | 无锁机制 | 必须持有对象监视器锁[^4] | | 唤醒顺序 | 精准唤醒指定线程 | 随机唤醒等待队列中的线程 | | 许可证机制 | 支持许可凭证累积(unpark) | 无类似机制 | | 异常处理 | 无检查异常 | 需处理InterruptedException| | 使用场景 | 并发框架底层实现 | 常规线程间通信 | #### 三、实现原理详解 1. **Object.wait() 工作流程**: ```java synchronized(obj) { // 必须获取对象锁[^2] while(condition) { obj.wait(); // 释放锁并进入等待队列 } // 被唤醒后自动重新获取锁 } ``` 2. **LockSupport 工作机制**: ```java LockSupport.unpark(targetThread); // 先发放许可 LockSupport.park(); // 有许可立即返回,无许可阻塞[^3] ``` #### 四、典型应用场景 1. **Object.wait适用场景**: - 生产者消费者模式 - 条件变量等待(需配合synchronized使用) - 经典线程间通信场景 2. **LockSupport优势场景**: - 实现高级同步器(如AQS) - 需要先唤醒后阻塞的特殊逻辑 - 避免锁竞争引发的性能问题 - 精确控制特定线程状态 #### 五、中断处理差异 - $LockSupport.park()$响应中断时**直接返回**,需通过$Thread.interrupted()$检测中断状态[^5] - $Object.wait()$被中断会**抛出InterruptedException**,需通过try-catch处理[^1] #### 六、注意事项 1. 错误使用示例: ```java Object o = new Object(); o.wait(); // 抛出IllegalMonitorStateException[^2] ``` 2. 正确配合使用方式: ```java Thread target = new Thread(() -> { LockSupport.park(); System.out.println("被唤醒"); }); target.start(); LockSupport.unpark(target); // 提前发放许可保证立即执行 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值