Java-初步认识-第十四章-线程间通信-多生产者多消费者问题-JDK1.5新特性-Condition

一.

现在wait方法和notifyAll方法,我们比较纠结。为什么这么说,之前同步里面的锁是我们自定义的,比如this,obj,而现在这个锁是我们自己new的,并且是根据1.5之后的锁对象来完成的。

以前写this和obj时,wait方法和notifyAll方法都是在这个锁上进行的操作,现在锁没了,现在的锁是lock。这个wait方法还能去操作this么?确切说,wait方法不能操作this这个锁上的线程了,因为线程的锁换了。应该用lock锁上的方法了,有的人直接改成lock.wait();

这么理解是对的,但是写法上有点变化,升级完的东西和以前有些不一样。用锁上的wait绝对是正确的思想,因为我们知道这种监视器的方法要根据该监视器所监视线程来操作。看下面的句子,

现在来阐述一下上面的截图是什么意思,

就以前的截图中同步来讲,对于同步来讲,锁上只能有一组监视器方法。什么意思呢?假设我这个锁是this的话,这个this锁上只有这么一组wait,notify,notifyAll这个方法。每个锁上绑定一组,因为每个锁都是object这个类的子类,它就直接拿这么一组方法。之前我们说的r.wait,r就是锁,它里面只能有这么一组wait,notify。而到了新版本里面,有一点改变了,

condition将object中的方法进行了封装,将这组监视器(wait,notify,notifyAll)单独封装成一个condition对象,而一个lock锁上可以挂多个conditon,每个condition都有一组监视器,

在上图中,有个obj。它里面只有一组wait,notify,notifyAll方法,因为只有一个对象嘛,只有一组。这三个方法就可以对这个锁进行操作了。你这同步函数只有一个锁,可以一旦锁变成对象以后,这个锁上可以挂多个锁,它可以将监视器方法封装成conditon对象。

何为condition呢?

上图conditon对象中,有一组方法,而且这个conditon对象有很多组,它们同属于一个锁

换句话说,这些conditon的方法都能都可以作用到这个锁的线程上。

以前的时候,一个锁只有一组方法(wait,notify,notifyAll),现在一个锁上可以挂多个。之前讲述的时候,object是锁,也是对象,里面封装着锁和一组方法,现在是将锁和方法分开来,锁用lock来表示,而一组方法用condition封装成对象,方法对象可以有很多个同时挂在一个锁上。

condition和lock之间有什么关系么?

截图中显示,通过newConditon()方法,我们随时可以拿到监视器方法实例。

在condition类的方法中,重新表述了一下wait,notify,notifyAll三个方法。名称变化了,功能没变。

await,signal,signalAll三个方法。

以前的时候,在object类中,有一组wait,notify,notifyAll的方法。同时创建一个自定义的类Demo,作为锁,new Demo就是锁对象。这个Demo类继承了object类,也就具备了这样一组方法。要将锁对象放入同步函数或者同步代码块中。

现在,我们将object类中操作监视器的方法封装成condition对象。本来锁和方法是封装在一起的,现在都分开来封装成对象。

从截图中可以看到,一个lock锁上,可以建立多个conditon方法。个锁上有两组监视器。每个监视器里都有之前谈论的三个方法。

lock的目的是为了替代同步,而conditon的目的是为了替代object中的方法。

监视器必须监视锁上的线程才可以。

现在回过来改写原先的代码,

原先根据object.wati()的写法,写成的lock.wait()要进行修改。

conditon是监视器,是lock这个锁上的,这个监视器会对这个lock锁上的线程进行操作。

截图中的程序被还原成最早的样子。

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();

    }
}

猜你喜欢

转载自blog.csdn.net/fighting_future/article/details/80397646