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 王菲:女
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。