学习笔记7:wait(),notify()与notifyAll()及消费者生产者小案例

1.wait(),notify()与notifyAll():java

    wait(),notify()与notifyAll方法是java.lang.Object类的方法,因此这些方法不能被子类重写,Object类是全部类的超类。
ide

void wait() 致使线程进入等待状态,直到它被其余线程经过notify()或者notifyAll唤醒
void wait(long t) //毫秒
在其余线程调用此对象的 notify() 方法或notifyAll()方法,或者超过指定的时间量前,致使当前线程等待。
void wait(long t, int n)

a.  其余线程经过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。函数

b.  timeout 毫秒值与 nanos 毫微秒参数值之和指定的超时时间已用完。 测试

// wait(0) 与wait(0,0)相同this

void notify()
随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。 (单个线程)
void notifyAll()

唤醒在此对象监视器上等待的全部线程。spa



wait(),notify(),notifyAll()必须写在同步方法中(synchronized方法内部或者synchronized块内部),这是由于这几个方法要求当前正在运行Object.wait()方法的线程拥有Object的对象锁,即当前线程必须拥有此对象监视器,不然将会抛出IllegalMonitorStateException(若是当前线程不是此对象监视器的全部者)。即便你确实知道当前上下文线程确实拥有了对象锁,也不能将Object.wait()这样的语句写在当前上下文中。线程


wait():释放占有的对象锁,线程进入等待池,释放cpu,而其余正在等待的线程便可抢占此锁,得到锁的线程便可运行程序。而sleep()不一样的是,线程调用此方法后,会休眠一段时间,休眠期间,会暂时释放cpu,但并不释放对象锁。也就是说,在休眠期间,其余线程依然没法进入此代码内部。休眠结束,线程从新得到cpu,执行代码。wait()和sleep()最大的不一样在于wait()会释放对象锁,而sleep()不会code

notify(): 该方法会唤醒由于调用对象的wait()而等待的线程,其实就是对对象锁的唤醒,从而使得wait()的线程能够有机会获取对象锁。调用notify()后,并不会当即释放锁,而是继续执行当前代码,直到synchronized中的代码所有执行完毕,才会释放对象锁。JVM则会在等待的线程中调度一个线程去得到对象锁,执行代码。须要注意的是,wait()和notify()必须在synchronized代码块中调用。notifyAll()则是唤醒全部等待的线程。orm


2.简单的生产者消费者例子:对象

//首先设定一个存放产品的缓冲区:

public class CollectionBuffer {
	//缓冲区最大存储量
	private final int MAX_SIZE = 100;
	//缓冲区存储量载体
	LinkedList<Object> list = new LinkedList<Object>();  // 此实现并不是同步 

	public LinkedList<Object> getList() {
		return list;
	}
	public void setList(LinkedList<Object> list) {
		this.list = list;
	}
	public int getMAX_SIZE() {
		return MAX_SIZE;
	}
	
	//生产产品 num 个
	public void produce( int num ){
		//同步代码块
		synchronized(list){
			//若是仓库剩余量不足,即生产产品可能过多  
			while( list.size() + num > MAX_SIZE ){
				System.out.println("即将生产产品数量为: " + num +"  但已有库存量为: "+ list.size() +"  暂时不能再进行生产任务<产品数量会大于最大库存量>");
				try {
					//等会再生产,陷入等待状态(阻塞) 会释放对象锁,而sleep不会
					list.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//若是知足条件,则生产产品:
			for( int i=1;i<=num;i++){
				list.add( new Object() );
			}
			
			System.out.println("已经生产产品数量为:" + num  + "  现生产后新的库存量为:" + list.size() );
			
			list.notifyAll();
		}
	}
	

	//消费产品 num 个
	public void consume( int num ){
		// 同步代码块
		synchronized(list){
			while( list.size() < num ){
				System.out.println("想要消费产品数量为: " + num +"  但当前库存产品量为: " + list.size() +"   暂时还不能消费<库存量小于消费量>");
				try {
					// 不知足消费条件,等待(阻塞)
					list.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			//若是知足消费条件, 即库存量足够消费者消费 消费量小于库存量。
			for( int i=1;i<=num;i++){
				list.remove();
			}
			System.out.println("已经消费产品数量为: " + num  + "  现消费后新的库存量为: " + list.size() );
			
			list.notifyAll();
		}
	}
	
}


// 生产者:

public class Producer extends Thread {
	// 每次生产的产品量
	private int num;
	
	//存放的仓库(缓冲容器)
	private CollectionBuffer collectionBuffer;

	// 构造函数 设置存储缓冲区仓库
	public Producer(CollectionBuffer collectionBuffer){
		this.collectionBuffer = collectionBuffer;
	}
	
	@Override
	public void run() {
		 // 调用仓库缓冲区CollectionBuffer的生产函数  
		collectionBuffer.produce(num);
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public CollectionBuffer getCollectionBuffer() {
		return collectionBuffer;
	}

	public void setCollectionBuffer(CollectionBuffer collectionBuffer) {
		this.collectionBuffer = collectionBuffer;
	}
	
}


//消费者:
public class Consumer extends Thread{
	//每次要消费的产品量:
	private int num;
	
	//消费产品的缓冲仓库区
	private CollectionBuffer collectionBuffer;
	
	//构造函数 指定消费商品的缓冲区
	public Consumer(CollectionBuffer collectionBuffer){
		this.collectionBuffer = collectionBuffer;
	}
	
	@Override
	public void run() {
		//调用缓冲区中的消费产品的函数,指定消费量
		collectionBuffer.consume(num);
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public CollectionBuffer getCollectionBuffer() {
		return collectionBuffer;
	}

	public void setCollectionBuffer(CollectionBuffer collectionBuffer) {
		this.collectionBuffer = collectionBuffer;
	}

}

// 测试类:
public class TestPC {
	public static void main(String[] args) throws InterruptedException {
		
		//建立仓库缓冲区对象
		CollectionBuffer cb = new CollectionBuffer();
		
		//建立多个生产者对象
		Producer p1 = new Producer(cb);
		Producer p2 = new Producer(cb);
		Producer p3 = new Producer(cb);
		Producer p4 = new Producer(cb);
		Producer p5 = new Producer(cb);
		Producer p6 = new Producer(cb);
		//建立多个消费者对象
		Consumer c1 = new Consumer(cb);
		Consumer c2 = new Consumer(cb);
		Consumer c3 = new Consumer(cb);
		Consumer c4 = new Consumer(cb);
		Consumer c5 = new Consumer(cb);
		Consumer c6 = new Consumer(cb);
		
		//开始设置生产者生产产品数量
		p1.setNum(10);
		p2.setNum(20);
		p3.setNum(30);
		p4.setNum(60);
		p5.setNum(80);
		p6.setNum(90);
		
		//开始让消费者消费产品数量
		c1.setNum( 80 );
		c2.setNum( 60 );
		c3.setNum( 50 );
		c4.setNum( 35 );
		c5.setNum( 20 );
		c6.setNum( 10 );
		
		
		// 让线程开始执行
		c1.start();
		c2.start();
		p1.start();
		p2.start();
		c6.start();
		p4.start();
		c3.start();
		p3.start();
		p5.start();
		c4.start();
		p6.start();
		c5.start();
		
	}

}
相关文章
相关标签/搜索