博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JUC——线程同步锁(Condition精准控制)
阅读量:6424 次
发布时间:2019-06-23

本文共 5491 字,大约阅读时间需要 18 分钟。

  在进行锁处理的时候还有一个接口:Condition,这个接口可以由用户来自己进行锁的对象创建。

  Condition的作用是对锁进行更精确的控制。

  Conditionawait()方法相当于Objectwait()方法,Conditionsignal()方法相当于Objectnotify()方法,ConditionsignalAll()方法相当于ObjectnotifyAll()方法。

  不同的是Objectwait(), notify(), notifyAll() 方法是和“同步锁”(synchronized关键字)捆绑使用的;而Condition是需要与“互斥锁/共享锁”捆绑使用。

  Object Condition
休眠 wait() await()
唤醒单个线程 notify() signal()
唤醒多个线程 notifyAll() signalAll()

 

 

 

 

范例:观察Condition的基本使用

package so.strong.mall.concurrent;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ConditionDemo {    private static String msg = null; //设置一个字符串    public static void main(String[] args)  throws Exception{        final Lock myLock = new ReentrantLock(); //实例化Lock接口对象        final Condition condition = myLock.newCondition(); //创建一个新的Condition接口对象        myLock.lock();        //如果现在不进行锁定,那么Condition无法执行等代理处理机制,会出现IllegalMonitorStateException        try {            new Thread(new Runnable() {                @Override                public void run() {                    myLock.lock();                    try {                        msg = "itermis.com";                        condition.signal(); //唤醒等待的Condition                    } finally {                        myLock.unlock();                    }                }            }).start();            condition.await(); //线程等待            System.out.println("*******主线程执行完毕,msg="+msg);        } finally {            myLock.unlock(); //解除阻塞状态        }    }} //*******主线程执行完毕,msg=itermis.com

  与之前的Object相比,唯一的区别在于:现在看不见明确的synchronized关键字,而取代synchronizedLock接口中的lock(),unlock()两个方法,而后在阻塞状态(同步状态)下可以使用Condition中的await()signal()方法进行等待与唤醒的操作处理。

 

范例:实现数据的缓冲控制

package so.strong.mall.concurrent;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author Termis * @date 2018/5/3 */public class DataBufferDemo {    public static void main(String[] args) {        final DataBuffer db = new DataBuffer();        for (int i = 0; i < 3; i++) { //创建3个写线程            new Thread(new Runnable() {                @Override                public void run() {                    for (int j = 0; j < 2; j++) {                        try {                            TimeUnit.SECONDS.sleep(1);                        } catch (Exception e) {                            e.printStackTrace();                        }                        db.put(Thread.currentThread().getName() + "写入数据,j=" + j);                    }                }            }, "生产者-" + i).start();        }        for (int i = 0; i < 5; i++) { //创建5个读线程            new Thread(new Runnable() {                @Override                public void run() {                    while (true) {                        try {                            TimeUnit.SECONDS.sleep(3);                        } catch (Exception e) {                            e.printStackTrace();                        }                        System.out.println("[(" + Thread.currentThread().getName() + ")CONSUMER]" + db.get());                    }                }            }, "消费者-" + i).start();        }    }}class DataBuffer { //进行数据的缓冲操作控制    private static final int MAX_LENGTH = 5; // 该类之中保存的数组长度的个数为5    private Object[] data = new Object[MAX_LENGTH]; //定义一个数组进行全部数据的保存控制    private Lock myLock = new ReentrantLock(); //创建数据锁    private Condition putCondition = myLock.newCondition(); //数据保存的Condition控制    private Condition getCondition = myLock.newCondition(); //数据读取的Condition控制    private int putIndex = 0; //写入数据的索引    private int getIndex = 0; //读取数据的索引    private int count = 0; //当前保存的元素个数    public Object get() {        Object getObj = null;        this.myLock.lock();        try {            if (this.count == 0) //没有写入                this.getCondition.await(); //读取的线程要进行等待            getObj = this.data[this.getIndex++]; //读取指定索引数据            if (this.getIndex == MAX_LENGTH)                this.getIndex = 0; //重新开始读            this.count--; //因为读了一个数据之后,现在需要减少个数            this.putCondition.signal(); //告诉写线程可以写入        } catch (Exception e) {            e.printStackTrace();        } finally {            this.myLock.unlock();        }        return getObj;    }    public void put(Object obj) { //进行缓冲数据的写入操作        this.myLock.lock(); //进入独占锁状态        try {            if (this.count == MAX_LENGTH)  //保存的数据已经满了                this.putCondition.await(); //暂时先别进行数据保存了            this.data[this.putIndex++] = obj; //保存当前数据            if (this.putIndex == MAX_LENGTH) //现在索引已经写满                this.putIndex = 0; //重置数组操作的索引脚标            this.count++; //保存的个数需要做一个追加            this.getCondition.signal(); //唤醒消费线程            System.out.println("[(" + Thread.currentThread().getName() + ")写入缓冲-put()]" + obj);        } catch (Exception e) {            e.printStackTrace();        } finally {            this.myLock.unlock(); //不管如何最终一定要进行解锁        }    }}
[(生产者-2)写入缓冲-put()]生产者-2写入数据,j=0[(生产者-1)写入缓冲-put()]生产者-1写入数据,j=0[(生产者-0)写入缓冲-put()]生产者-0写入数据,j=0[(生产者-1)写入缓冲-put()]生产者-1写入数据,j=1[(生产者-2)写入缓冲-put()]生产者-2写入数据,j=1[(消费者-3)CONSUMER]生产者-2写入数据,j=0[(消费者-4)CONSUMER]生产者-1写入数据,j=1[(消费者-1)CONSUMER]生产者-0写入数据,j=0[(消费者-2)CONSUMER]生产者-1写入数据,j=0[(生产者-0)写入缓冲-put()]生产者-0写入数据,j=1[(消费者-0)CONSUMER]生产者-2写入数据,j=1[(消费者-3)CONSUMER]生产者-0写入数据,j=1

  对于生产者和消费者模型的实现,除了多线程基础实现之外,也可以采用以上的模式利用LockCondition进行精确控制。

 

转载于:https://www.cnblogs.com/itermis/p/8986899.html

你可能感兴趣的文章
关于ASP.NET MVC4 Web API简单总结
查看>>
BGP最新的AS号:4-byte-as 转换为十进制及AS号兼容性
查看>>
Windows2008server R2 组策略批量更改本地管理员密码
查看>>
ubutnu安装geany
查看>>
webservice 之 Java CXF实战效果 RS WS(一)
查看>>
iOS企业证书发布流程
查看>>
我的友情链接
查看>>
Repository 与 DAO
查看>>
【vmcloudlab】Hyper-V平台上安装Linux集成服务
查看>>
Zabbix监控Windows主机
查看>>
Docker的文件系统
查看>>
IBM x3850 RAID5数据恢复方案及过程
查看>>
移动计算领域五大机遇:交通运输优势待挖掘
查看>>
如何把win7 旗舰版升级到sp1最新版本
查看>>
android 调用系统界面
查看>>
Software Enginering-------using git
查看>>
浅谈IP地址-1
查看>>
我的友情链接
查看>>
C#中的线程池使用(一)
查看>>
利用Windows Server Backup功能备份活动目录
查看>>