java-Lock篇之condition.<二>

1.condition

condition是java.util.concurrent.locks下的接口,Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解

成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,

Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

class BoundedBuffer {
   final Lock lock = new ReentrantLock();//锁对象
   final Condition notFull  = lock.newCondition();//写线程条件
   final Condition notEmpty = lock.newCondition();//读线程条件   

   final Object[] items = new Object[100];//缓存队列
   int putptr/*写索引*/, takeptr/*读索引*/, count/*队列中存在的数据个数*/;  

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)//如果队列满了
         notFull.await();//阻塞写线程,this.wait()
       items[putptr] = x;//赋值
       if (++putptr == items.length) putptr = 0;//如果写索引写到队列的最后一个位置了,那么置为0
       ++count;//个数++
       notEmpty.signal();//唤醒读线程,this.notify()
     } finally {
       lock.unlock();
     }
   }  

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)//如果队列为空
         notEmpty.await();//阻塞读线程,this.wait()         Object x = items[takeptr];//取值
       if (++takeptr == items.length) takeptr = 0;//如果读索引读到队列的最后一个位置了,那么置为0
       --count;//个数--
       notFull.signal();//唤醒写线程,this,notify()
       return x;
     } finally {
       lock.unlock();
     }
   }
 }  

演示用synchronized和lock方式使用的两个小例子

使用synchronized的例子

public class SynDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Q q=new Q ();
         Consumer c=new Consumer(q);
         Producer p=new Producer (q);
         new Thread (c).start();
         new Thread (p).start();

    }

}
//消费者线程(读取)
class Consumer implements Runnable
{
    private Q q=null;
    public Consumer (Q q)
    {
        this.q=q;
    }
    public void run ()
    {
         while(true)
         {
             //System.out.println(Thread.currentThread().getName());
            try {
                q.get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         }
    }

}
//生产者线程(更改)
class Producer implements Runnable
{
    private Q q=null;
    private int num=1;
    public Producer (Q q)
    {
      this.q=q;
     }
     public void run ()
     {
         while(true)
         {

             //System.out.println(Thread.currentThread().getName());
             if(num==1)
             {
                try {
                    q.put("陈奕迅","男");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
             }
             else if(num==0)
             {
                 try {
                    q.put("王菲","女");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
             }

        num=(num+1)%2;
         }
     }
}
//共同操作的数据Q,由线程对其进行修改,读取,
//因为要修改和读取同步(即两个方法的同步锁为Q对象),且数据在Q内部,所以应具有操作数据的方法
class Q
{
    private String name;
    private String sex;
  private boolean flag=true;//以标志位来控制更改或读取操作。
    //更改的同步方法
    public synchronized void put(String name,String sex) throws InterruptedException
    {
        //默认标志位为true时更改否则等待
        if(!isFlag())
            wait();
      this.name=name;
        this.sex=sex;
       //更改完后换读取,且唤醒读取(为false标志)的线程
        this.flag=false;
        notify();
         System.out.println(Thread.currentThread().getName());

    }
  //读取的同步方法
  public synchronized void get() throws InterruptedException
    {
        //默认标志位为flase时读取否则等待
        if(isFlag())
            wait();
        System.out.println(this.name+":"+this.sex);
        //读取完后换更改,且唤醒更改(为true)的线程
        this.flag=true;
        notify();
         System.out.println(Thread.currentThread().getName());

    }

    public boolean isFlag()
    {
           return flag;
    }
    public void setFlag(boolean flag)
    {
           this.flag=flag;
    }
    public String getName()
  {
        return name;
    }
    public void setName(String name)
    {
        this.name=name;
    }
  public String getSex()
  {
        return sex;
    }
    public void getSex(String sex)
    {
        this.sex=sex;
    }

}

使用lock例子,只需要修改Q类内部即可

//synchronized 可用Lock代替
//object的wait,notify和notifyAll方法可用condition对象下对应的方法代替。
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

//共同操作的数据Q,由线程对其进行修改,读取,
//因为要修改和读取同步(即两个方法的同步锁为Q对象),且数据在Q内部,所以应具有操作数据的方法
class Q
{
    private String name;
    private String sex;
  private boolean flag=true;//以标志位来控制更改或读取操作。
  private final  ReentrantLock l=new ReentrantLock();
  private Condition rc=l.newCondition(); //读线程条件
  private Condition wc=l.newCondition();//写线程条件
    //更改的同步方法
    public   void put(String name,String sex) throws InterruptedException
    {
        l.lock();
        try{
        //默认标志位为true时更改否则等待
        while(!isFlag())
            wc.await();
      this.name=name;
        this.sex=sex;
       //更改完后换读取,且唤醒读取(为false标志)的线程
        this.flag=false;
        rc.signal();
         System.out.println(Thread.currentThread().getName());
        }
        finally{
         l.unlock();
        }
    }
  //读取的同步方法
  public   void get() throws InterruptedException
    {
       l.lock();
       try
       {
        //默认标志位为flase时读取否则等待
        while(isFlag())
            rc.await();
        System.out.println(this.name+":"+this.sex);
        //读取完后换更改,且唤醒更改(为true)的线程
        this.flag=true;
        wc.signal();
          System.out.println(Thread.currentThread().getName());
       }
       finally{
       l.unlock();
       }
    }

    public boolean isFlag()
    {
           return flag;
    }
    public void setFlag(boolean flag)
    {
           this.flag=flag;
    }
    public String getName()
  {
        return name;
    }
    public void setName(String name)
    {
        this.name=name;
    }
  public String getSex()
  {
        return sex;
    }
    public void getSex(String sex)
    {
        this.sex=sex;
    }

}

输出结果:

陈奕迅:男
Thread-0
Thread-1
王菲:女
Thread-0
Thread-1
陈奕迅:男
Thread-0
Thread-1
王菲:女
时间: 2024-07-29 10:44:44

java-Lock篇之condition.<二>的相关文章

Java提高篇(三二)-----List总结

前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点能够对List接口有了比較深的了解了.仅仅有通过归纳总结的知识才是你的知识.所以以下LZ就List接口做一个总结.推荐阅读: java提高篇(二一)-----ArrayList java提高篇(二二)-----LinkedList java提高篇(二九)-----Vector Java提高篇(三一)-----Stack 一.List接口概述 List接口,成

java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.concurrent.locks.ReentrantLock 锁,JDK也为我们提供了与此功能相应的类java.util.concurrent.locks.Condition.Condition与重入锁是通过lock.newCondition()方法产生一个与当前重入锁绑定的Condtion实例,我们

【转】java提高篇(二)-----理解java的三大特性之继承

[转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句话中最引人注目的是"复用代码",尽可能的复用代码使我们程序员一直在追求的,现在我来介绍一种复用代码的方式,也是java三大

Java提高篇(三六)-----java集合细节(二):asList的缺陷

在实际开发过程中我们经常使用asList讲数组转换为List,这个方法使用起来非常方便,但是asList方法存在几个缺陷: 一.避免使用基本数据类型数组转换为列表 使用8个基本类型数组转换为列表时会存在一个比较有味的缺陷.先看如下程序: public static void main(String[] args) { int[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); System.out.println("list'size:&

java提高篇(二二)-----LinkedList

摘自http://blog.csdn.net/chenssy/article/details/18099417  java提高篇(二二)-----LinkedList 一.概述 LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现.基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些. LinkedList实现所有可选

JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序员杜鹏程的博客:http://blog.csdn.net/m366917 我们来继续学习多线程 Lock锁的使用 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock Lock void lock():获取锁 v

java提高篇(二九)-----Vector

在java提高篇(二一)-–ArrayList.java提高篇(二二)-LinkedList,详细讲解了ArrayList.linkedList的原理和实现过程,对于List接口这里还介绍一个它的实现类Vector,Vector 类可以实现可增长的对象数组. 一.Vector简介 Vector可以实现可增长的对象数组.与数组一样,它包含可以使用整数索引进行访问的组件.不过,Vector的大小是可以增加或者减小的,以便适应创建Vector后进行添加或者删除操作. Vector实现List接口,继承

java学习笔记 第二篇 核心技术(二)

第十四章 集合类 集合类用来存放对象的引用.继承关系如下图: 14.1 Collection 接口 是层次结构中的根接口,构成Collection的单位称为元素.Collection接口不能直接使用,但该接口提供了添加元素.删除元素.管理数据的方法. Collection接口常用方法: 14.2 List 集合 包括List接口以及List集合的所有实现类.List集合中的元素允许重复,各元素循序就是对象插入的顺序 1.List接口,两个重要方法: get(int index): 获取指定索引位

Java提高篇(三二)-----List总结

前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点可以对List接口有了比较深的了解了.只有通过归纳总结的知识才是你的知识.所以下面LZ就List接口做一个总结.推荐阅读: java提高篇(二一)-----ArrayList java提高篇(二二)-----LinkedList java提高篇(二九)-----Vector Java提高篇(三一)-----Stack 一.List接口概述 List接口,成为