天天看点

JAVA多线程之Object的(wait()、notify())

如果需要调用一个对象的wait()方法,当前线程必须持有这个对象的锁,因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

  调用某个对象的wait()方法,相当于让当前线程交出此对象的锁,然后进入等待状态,等待后续再次获得此对象的锁(Thread类中的sleep方法使当前线程暂停执行一段时间,从而让其他线程有机会继续执行,但它并不释放对象锁);

  notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的monitor的话,则只能唤醒其中一个线程,具体唤醒哪个线程则不得而知。具体参照下面生产者与消费者的实例:

  缓存池:

package nc.com.thread.Condition.example;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 
* @ClassName: CacheCondition 
* @Description: 生产者与消费者共同持有的蛋糕存取池
* @author A18ccms a18ccms_gmail_com 
* @date 2016-3-20 下午03:29:40 
*
 */
public class CacheCondition {
    private int limit=100;
	private Lock lock = new ReentrantLock();
	private Condition isEmpty=lock.newCondition();
	private Condition isFull= lock.newCondition();
	private List<Cake> cache=new ArrayList<Cake>(limit);
	private CacheCondition(){
		
	}
	private static class SingleHoder{
		private static CacheCondition instance = new CacheCondition();
	}
	
  public static CacheCondition getInstance(){
	  return SingleHoder.instance;
  }
	
  public void put(Cake cake){
	  try {
		  lock.lockInterruptibly();
		  while(cache.size()>=limit){
			  System.out.println(""+Thread.currentThread().getName()+"等待放入蛋糕,缓存池已满");
			  isFull.await();
	    	  System.out.println(""+Thread.currentThread().getName()+"被唤醒,可以继续生产");
		  }
		  cache.add(cake);
		  isEmpty.signal();
		  System.out.println(""+Thread.currentThread().getName()+"放入蛋糕:"+cake.toString()+",池中总共蛋糕"+cache.size());
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		lock.unlock();
	}
  }
  
  public Cake getCake(){
		Cake cake=null;
		try {
			 lock.lockInterruptibly();
			 while(cache.size()<=0){
				 System.out.println(""+Thread.currentThread().getName()+"等待获取蛋糕,缓存池已空");
				 isEmpty.await(); 
				 System.out.println(""+Thread.currentThread().getName()+"被唤醒,缓存池已有蛋糕");
			 }
			 cake=cache.remove(0);
			 isFull.signal();
			 System.out.println(""+Thread.currentThread().getName()+"获得蛋糕:"+cake.toString()+",池中剩下总共蛋糕"+cache.size());
		} catch (Exception e) {
        e.printStackTrace();
		}finally{
			lock.unlock();
		}
		return cake;
	}

}
           

蛋糕类:

package nc.com.thread.Condition.example;

/**
 * 
* @ClassName: Cake 
* @Description: 蛋糕类 
* @author A18ccms a18ccms_gmail_com 
* @date 2016-3-20 下午03:31:02 
*
 */
public class Cake {

	private String color;
	private int price;

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Cake [color=" + color + ", price=" + price + "]";
	}

}
           

生产者:

package nc.com.thread.Condition.example;
/**
 * 
* @ClassName: Productor 
* @Description: 蛋糕生产者
* @author A18ccms a18ccms_gmail_com 
* @date 2016-3-20 下午03:32:05 
*
 */
public class Productor  implements Runnable{

	@Override
	public void run() {
		try {
			while(true){
				Cake  cake =  new Cake();
				cake.setPrice((int) Thread.currentThread().getId());
				cake.setColor(""+Thread.currentThread().getName()+"放入red");
				CacheCondition.getInstance().put(cake);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
           

消费者:

package nc.com.thread.Condition.example;

/**
 * 
* @ClassName: Customer 
* @Description: 消费者 
* @author A18ccms a18ccms_gmail_com 
* @date 2016-3-20 下午03:32:54 
*
 */
public class Customer  implements Runnable{

	@Override
	public void run() {
		try {
			while(true){
				Thread.sleep(2000);
				Cake  cake=CacheCondition.getInstance().getCake();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
           

测试类:

package nc.com.thread.Condition.example;


public class ThreeConditionCommunication {
	public static void main(String[] args) {
		
		 for(int num =0;num<10;num++){
			 Customer c = new Customer();
			 new Thread(c,"消费者"+num).start();
			 
		 }
		 try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 for(int num =0;num<2;num++){
			 Productor p = new Productor();
			 new Thread(p,"生产者"+num).start();
		 }
	}
}