一.
在1.5版本中,将原先的形式进行了改变,但是功能并没有任何变化,那么这么做的原因是什么?
以前,我们一个锁上只有一组监视器,这组监视器既监视着生产者,又监视着消费者。这组监视器能将生产者和消费者全都wait,也能将生产者和消费者全都唤醒。或者notify也行,它也能将其中一条线程唤醒,而其中一条不能确定是谁,有可能是本方,也可能是对方。
现在我们的线程进行了分类,一组负责生产,一组负责消费。我们希望生产者能够唤醒消费者,消费者唤醒生产者。如果搞两个监视器,一组监视生产者,一组监视消费者,这就靠谱了。
以前怎么弄的,生产者得具备一个锁,消费者得具备另一个锁,因为一个锁只能有一个监视器,现在一个锁上有多个监视器。现在我们四个线程用的是同一把锁,但是监视器不一样,是两个监视器,一个监视生产者,一个监视消费者。生产这边拿的是消费的唤醒,唤醒的就是消费的线程。
如果是两个锁,那么生产只能用于生产,消费只能用于消费(这是说的以前的做法),它俩可以同时运行,就会导致问题。
而我们现在生产里面在操作的时候,消费是不能动的,这叫同一个锁。
producer_con生产者监视器,consumer_con消费者监视器。
一个锁上挂着多个监视器。
package t4; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @author 高小硕 * jdk1.5以后将同步和锁封装成对象 * * 并将操作锁的隐式方式定义到了该对象中。 * 将隐式动作变成了显示动作 * * Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作 * 同时更为灵活。可以一个锁上加上多组监视器。 * * lock():获取锁 * unlock():释放锁,通常需要定义在finall代码块中 * * Condition接口:出现替代了Object中的wait notify notifyAll方法 * * 将这些监视器方法单独进行了封装,变成Condition监视器对象。 * 可以任意锁进行组合。 *await(); *signal(); *signalAll(); * * */ class Resource { private String name; private int count=1; private boolean flag=false; //创建一个锁对象 Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象 //使用两个监视器 Condition producer_con = lock.newCondition(); Condition consumber_con = lock.newCondition(); public void set(String name) { lock.lock(); try { while(flag) // try{wait();}catch(InterruptedException e){} try{producer_con.await();}catch(InterruptedException e){} this.name=name+count; count++;//2 3 4 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name); flag=true; consumber_con.signal();//唤醒对方的线程 } finally { lock.unlock(); } } public void out() { lock.lock(); try { while(!flag) // try{wait();}catch(Exception e){} try{consumber_con.await();}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+".....消费者......"+this.name); flag=false; producer_con.signal(); } finally { lock.unlock(); } } } class Producer implements Runnable { private Resource r; public Producer(Resource r) { this.r=r; } public void run() { while(true) { r.set("烤鸭"); } } } class Consumer implements Runnable { private Resource r; public Consumer(Resource r) { this.r=r; } public void run() { while(true) { r.out(); } } } public class LockProducerConsumer { public static void main(String[] args) { Resource r=new Resource(); Producer pro=new Producer(r); Consumer con=new Consumer(r); Thread t1=new Thread(pro); Thread t2=new Thread(pro); Thread t3=new Thread(con); Thread t4=new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } }