利用Object的wait、notify来实现线程同步原理

认识Object.wait()方法:   
    导致当前线程等待,直到该对象的notify或notifyAll被执行。换句话说,这个方法行为效果完全与简单调用wait(0)一样。当前线程必须拥有对象监视器。线程释放对象监视器的所有权,等待直到另一个线程通过调用notify或notifyAll来通知等待对象监视器的线程们并唤醒。然后,当前线程等待重新获取对象监视器并继续执行。因为在一个参数的版本中,中断与伪唤醒是可能的,这个方法应该通常在一个循环中使用:
  synchronized (obj) {
    while (<condition does not hold>)
            obj.wait();
      ... // Perform action appropriate to condition
  }    
该方法必须同步执行的,否则会抛出IllegalMonitorStateException。

认识Object.wait(long)方法:  
   基本功能与Object.wait()相同,只是在指定时间间隔后,当前线程自动唤醒,并与其它线程竞争对象监视器,在获取对象监视器后,当前线程继续向前执行。

认识Object.notify方法:
    唤醒等待这个对象的监视器的单一线程。如果有很多线程在等待该对象监视器,则选择其中的一个来唤醒。这歌选择是任意的,与具体的实现相关。一个线程调用wait方法后就等待对象监视器。被唤醒的线程将在当前线程放弃对象锁后才能继续执行,它在竞争该对象锁方面没有任何可靠的特权或劣势。调用这个方法必须占有对象监视器。线程通过3中途径可以占有对象监视器:
(1)执行对象的同步方法;
(2)执行锁定对象的同步语句块;
(3)执行类对象的静态同步方法。
在某一时刻,只有一个线程占有对象监视器。该方法必须同步执行的,否则会抛出IllegalMonitorStateException。


通过下面的一个例子来说明:

final Object synObj = new Object();  
Thread t1 = new Thread(new Runnable() {
 @Override
 public void run() {
  synchronized(synObj) {
   System.out.println("T1获取synObj的对象监视器,开始执行同步块");
   try {
    TimeUnit.MINUTES.sleep(1);
    System.out.println("T1在 wait()时挂起了");
    synObj.wait();
    System.out.println("T1被T2唤醒后并重新获得synObj的对象监视器,继续执行");      
   }catch(InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("T1获取synObj的对象监视器,结束同步块");
  }    
 };
});
t1.start();


Thread t2 = new Thread(new Runnable() {
 @Override
 public void run() {
  System.out.println("T2启动,但是因为T1占用了synObj的对象监视器,则等待T1执行synObj.wait来释放它");
  synchronized(synObj) {
   try {
    System.out.println("在T1执行synObj.wait后,T2获取synObj的对象监视器,进入同步块");
    synObj.notify();
    System.out.println("T2执行synObj.notify(),T1被唤醒,但T2还在同步块中,没有释放synObj的对象监视器,T1等待synObj的对象监视器");
    TimeUnit.MINUTES.sleep(1);
    System.out.println("T2结束同步块,释放synObj的对象监视器,T1获取到synObj的对象监视器,并执行wait后面的操作");
   }catch(InterruptedException e) {
    e.printStackTrace();
   }
  }    
 };
});
t2.start();

<span style="font-size:18px;">final Object synObj = new Object();		
Thread t1 = new Thread(new Runnable() {
	@Override
	public void run() {
		synchronized(synObj) {
			System.out.println("T1获取synObj的对象监视器,开始执行同步块");
			try {
				TimeUnit.MINUTES.sleep(1);
				System.out.println("T1在 wait()时挂起了");
				synObj.wait();
				System.out.println("T1被T2唤醒后并重新获得synObj的对象监视器,继续执行");						
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("T1获取synObj的对象监视器,结束同步块");
		}				
	};
});
t1.start();


Thread t2 = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("T2启动,但是因为T1占用了synObj的对象监视器,则等待T1执行synObj.wait来释放它");
		synchronized(synObj) {
			try {
				System.out.println("在T1执行synObj.wait后,T2获取synObj的对象监视器,进入同步块");
				synObj.notify();
				System.out.println("T2执行synObj.notify(),T1被唤醒,但T2还在同步块中,没有释放synObj的对象监视器,T1等待synObj的对象监视器");
				TimeUnit.MINUTES.sleep(1);
				System.out.println("T2结束同步块,释放synObj的对象监视器,T1获取到synObj的对象监视器,并执行wait后面的操作");
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}				
	};
});
t2.start();</span>

输出:
T1获取synObj的对象监视器,开始执行同步块
T2启动,但是因为T1占用了synObj的对象监视器,则等待T1执行synObj.wait来释放它
T1在 wait()时挂起了
在T1执行synObj.wait后,T2获取synObj的对象监视器,进入同步块
T2执行synObj.notify(),T1被唤醒,但T2还在同步块中,没有释放synObj的对象监视器,T1等待synObj的对象监视器
T2结束同步块,释放synObj的对象监视器,T1获取到synObj的对象监视器,并执行wait后面的操作
T1被T2唤醒后并重新获得synObj的对象监视器,继续执行
T1获取synObj的对象监视器,结束同步块

注意,对象监视器就是对象锁,在object.notify()后,被唤醒的线程还不能立即执行,必须等待到对象锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值