chapter14_构建自定义的同步工具_1_状态依赖性的管理
时间:2019-03-19
本文章向大家介绍chapter14_构建自定义的同步工具_1_状态依赖性的管理,主要包括chapter14_构建自定义的同步工具_1_状态依赖性的管理使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
-
轮询方式
(1) 基类
@ThreadSafe public abstract class BaseBoundedBuffer<V> { @GuardedBy("this") private final V[] buf; @GuardedBy("this") private int tail; @GuardedBy("this") private int head; @GuardedBy("this") private int count; protected BaseBoundedBuffer(int capacity) { this.buf = (V[]) new Object[capacity]; } protected synchronized final void doPut(V v) { buf[tail] = v; if (++tail == buf.length) { tail = 0; } ++count; } protected synchronized final V doTake() { V v = buf[head]; buf[head] = null; if (++head == buf.length) { head = 0; } --count; return v; } public synchronized final boolean isFull() { return count == buf.length; } public synchronized final boolean isEmpty() { return count == 0; } }
(2) 将前提条件的失败传递给调用者
示例
@ThreadSafe public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V> { public GrumpyBoundedBuffer() { this(100); } public GrumpyBoundedBuffer(int size) { super(size); } public synchronized void put(V v) throws BufferFullException { if (isFull()) { throw new BufferFullException(); } doPut(v); } public synchronized V take() throws BufferEmptyException { if (isEmpty()) { throw new BufferEmptyException(); } return doTake(); } }
这种方式存在的问题:
异常应该用于真正发生异常条件的情况, 而缓存空或者满不属于异常情况.
这加大了调用者的负担(要处理异常); 并且导致有些功能无法实现(例如先到先处理FIFO, 调用者很可能不会保存元素的顺序)
(2) 真正的轮询方式
@ThreadSafe public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V> { private int SLEEP_GRANULARITY = 60; public SleepyBoundedBuffer() { this(100); } public SleepyBoundedBuffer(int size) { super(size); } public void put(V v) throws InterruptedException { while (true) { synchronized (this) { if (!isFull()) { doPut(v); return; } } Thread.sleep(SLEEP_GRANULARITY); } } public V take() throws InterruptedException { while (true) { synchronized (this) { if (!isEmpty()) { return doTake(); } } Thread.sleep(SLEEP_GRANULARITY); } } }
优点: 调用者无需catch异常; 提供了取消机制(Thread.sleep()中抛出InterruptedException直接向外抛)
问题: 睡眠时间SLEEP_GRANULARITY变量的值很微妙: 取的小的时候, 响应性好但是很多CPU时钟周期会被浪费(如果这个值是0那么一直被浪费称为__自旋等待__); 取的大的时候CPU使用率高但响应慢
-
条件队列
(1) 使得一组线程能够通过某种方式等待特定的条件为真
(2) Java的每个对象都可以作为内置锁, 每个对象也都可以作为一个条件队列
内置的API是wait, notify, notifyAll
(3) 对象的内置锁与其内部条件队列是相互关联的, 要调用对象X中条件队列的任何一个方法, 必须持有对象X上的锁
(4) Object.wait()会__自动释放锁__, 并请求操作系统__挂起当前线程__, 从而使得其他线程有机会获得这个锁;
当被挂起的线程醒来时, 它将在wait()返回之前__视图重新获取锁__
在重新请求锁时, 被唤醒的线程不具有特殊的优先级, 它将和其他要获取锁的线程一并竞争
(5) 示例
@ThreadSafe public class BoundedBuffer<V> extends BaseBoundedBuffer<V> { // CONDITION PREDICATE: not-full (!isFull()) // CONDITION PREDICATE: not-empty (!isEmpty()) public BoundedBuffer() { this(100); } public BoundedBuffer(int size) { super(size); } // BLOCKS-UNTIL: not-full public synchronized void put(V v) throws InterruptedException { while (isFull()) { this.wait(); } doPut(v); this.notifyAll(); } // BLOCKS-UNTIL: not-empty public synchronized V take() throws InterruptedException { while (isEmpty()) { this.wait(); } V v = doTake(); this.notifyAll(); return v; } }
- 想成为优秀程序员必知的要点
- Attribute(特性),怎么用才更好?
- 如何使用Airgeddon搭建基于软件的WIFI干扰器
- 还在写SQL的同志,去喝杯咖啡吧!
- 使用XSD编写具有智能提示的XML文件(以SQL-MAP脚本为实例)
- 一个利用CVE-2017-11292的APT样本技术分析(一)
- Attribute(特性),怎么用才更好? —— 字段编号被误解了
- PDF.NET的SQL日志 ASP.net 路径问题 详解
- 【自然框架】稳定版beta1——源码下载,Demo说明
- TOP语句放到表值函数外,效率异常低下的原因分析
- 常见.NET功能代码汇总 (3) 33,彻底关闭Excel进程
- Vue.js 入门指南之“前传”(含sublime text 3 配置) 1,下载安装Node.js2,配置Vue环境3,Vue初探4,配置sublime Text
- JavaScript的“原型甘露”
- JSP开发过程遇到的中文乱码问题及解决方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用 Eureka 简单实现服务健康监控日志分析
- Flask 入门系列教程(一)
- Flask 入门系列教程(二)
- CVE-2020-1472
- 盘点提高国内访问 GitHub 的速度的 9 种方案
- 如何用 Serverless 优雅地实现图片艺术化应用
- Unity3D网络通讯(四)--Socket通讯之Tcp通讯
- 笔记|Unity异步处理与UI Text显示的问题
- 项目中的全局缓存导致了内存泄露?
- 架构设计 | 分布式体系下,服务分层监控策略
- Hadoop框架:单服务下伪分布式集群搭建
- 架构设计 | 基于Seata中间件,微服务模式下事务管理
- 编程体系结构(03):Java集合容器
- SpringBoot2 集成日志,复杂业务下的自定义实现
- 事件统计 | performance_schema全方位介绍