MoreThread && wait && notify

 吐舌头 下面可是我亲手敲打的。。。。肩膀都酸了。。。本可以copy的。。。哎,但为了加深印象。。。顺便练练打字。。。

 

    经过网上查证,wait()允许我们将线程置入睡眠状态,同时又积极的等待条件发生改变,而且只有当一个notify()或notifyAll()发生改变时,线程才会被唤醒,并检查条件是否有变,这里就只用while判断。不能用if

     wait()允许我们将线程置入睡眠状态,也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend 是相同的,那和sleep,suspend有什么区别呢?

    区别1;wait 是Object类中的方法,sleep和suspend 是Thread 类中的方法

     区别2在于wait 同时又积极的等待条件发生改变。。这点很关键,sleep和suspend 无法做到。因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其他要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部执行完才有机会。在同步方法和同步块,

无论sleep还是suspend 都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放。。。sleep很贪婪哦

    而wait 却可以,它可以让同步方法或同步块暂时放弃对象锁,而将它暂时让给其他需要对象锁的人(这里是指程序块,或线程块)用,这意味着可在执行wait 期间调用线程对象中的其他同步方法。。。在其他情况下,这是不可能的。

    但是注意我前面说的,只是暂时放弃对象锁,暂时给其他线程用,我wait还是要把这个对象锁收回来的。。。。怎么收回来??啥时候收回来呢??

    第一种方法,限定借出去的时间,在wait 中设置参数,比如wait(1000),以毫秒为单位,就是说只借你一秒钟,然后就收回来

    第二种方法,让借出去的人通知我,他用完了,就还给我了。

    那么别人怎么通知我呢??相信大家都可以想到了,notify()。对,就是它。也只有在一个notify 或notifAll 发生变化时,线程才会被唤醒。。。啊啊啊,终于醒了

 

现在摆一个代码:生产者与消费者。。。。相当经典的面试题

 

package heng.java.Thread2;

public class MoreThread {
	public static void main(String[] args) {
		SyncStack ss = new SyncStack();
		Producer p = new Producer(ss);
		Consumer c = new Consumer(ss);
		new Thread(p).start();
		new Thread(c).start();
	}

}
class WoTou {
	int id;
	WoTou(int id){
		this.id = id;
	}
	public String toString(){
		return "WoTou:"+id;
	}
}

class SyncStack {
	int index = 0;
	WoTou []arrWT = new WoTou[6];
	
	public synchronized void push(WoTou wt){
		while(index == arrWT.length){
			try {
				//当wait时,将不再拥有锁,只能等到notify,才能再次拥有锁,这是和sleep最大的区别,sleep即使睡着,也依然拥有锁
				this.wait();//(只有锁住时,才能wait)当前的,正在我这个对象访问的线程wait。
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();//让消费者赶紧消费
		arrWT[index] = wt;
		index ++;
		
	}
	public synchronized WoTou pop(){
		while(index == 0){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
		index --;
		return arrWT[index];
	}
}

class Producer implements Runnable {
	SyncStack ss = null;
	Producer (SyncStack ss) {//要有个筐的引用
		this.ss = ss;
	}
	public void run(){
		for(int i=0; i<20; i++){
			WoTou wt = new WoTou(i);
			ss.push(wt);
			System.out.println("生产了:"+wt);
			try {
				Thread.sleep((int)(Math.random()*2));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Consumer implements Runnable {
	SyncStack ss = null;
	Consumer(SyncStack ss) {//要有个筐的引用
		this.ss = ss;
	}
	public void run(){
		for(int i=0; i<20; i++){
			WoTou wt = ss.pop();
	        System.out.println("消费了:"+wt);
			try {
				Thread.sleep((int)(Math.random()*1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(wt);
		}
	}
	
}







 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值