基于同步器的合并接口实现
来源:互联网 发布:淘宝的渠道管理在哪里 编辑:程序博客网 时间:2024/06/06 03:01
在上篇《高并发下合并接口请求》中是简单的基于计数器来实现,每个线程都会以一定的时间(10毫秒)间隔检查是否有接口返回。其中的延时可以把间隔设置的非常小,但所有线程的调度还是有些浪费CPU资源。近两天看Tomcat源码时无意发现了一个叫AbstractQueuedSynchronizer的同步器,这个是JDK并发包下提供的工具类,如著名的ReentrantLock就是基于此实现。
AbstractQueuedSynchronizer提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步类的基础框架。使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,一般子类推荐被定义为自定义同步类的内部类。该同步器即可以作为排他模式也可以作为共享模式,当它被定义为一个排他模式时,其他线程对其的获取就被阻止,而共享模式对于多个线程获取都可以成功。
同步器中FIFO队列的元素Node就是保存着线程引用和线程状态的容器,每个线程对同步器的访问,都可以看做是队列中的一个节点。当前线程如果获取不到锁,将当前线程构造成节点Node并加入sync队列尾,进入队列的每个线程都是一个节点Node,从而形成了一个双向队列。每个节点都是一个线程在进行自旋,判断依据就是自己是否是首节点的后继并且能够获资源,在释放时仅仅需要将资源还回去,然后通知一下后继节点并将其唤醒。
AbstractQueuedSynchronizer已经实现了线程管理,只需要继承它实现一个自定义的同步器即可。该同步器特征为:同一并发时刻第一个线程为独占锁,后续线程为共享锁(共享第一个线程的执行结果),最后一个线程清除缓存结果。可以在同步器中加个计数器、缓存变量以及配合自身的状态来实现。
当调用countUpOrAwait获取锁时,先计数器加1,并依次尝试获取共享锁、独占锁。获取共享只要判断下状态即可,这里的需求是合并接口调用,即使共享锁到独占锁过渡的时候,如果获取到了缓存数据则直接返回,如果获取的缓存数据为空则只要重试一次即可。主要是获取独占锁时要调用compareAndSetState来原子的尝试修改状态,锁状态定义3个值,分别是:1没有请求、0独占、-1共享。当独占线程执行完成后需调用setValue来把结果缓存到Sync中,这样一来也不用再单独定义一个缓存Map。最后就是调用countDown,计算数器减1并释放资源,如果是最后一个线程则还需清空关联的缓存变量。
--------------------------------
相关代码为:synchplay/easyJCommon
- 基于同步器的合并接口实现
- Java 并发包中AbstractQueuedSynchronizer 实现的同步器
- 同步器
- 同步器
- 基于FPGA的PCIe接口实现
- 自动化测试接口的实现,基于python
- 基于JQuery实现相同内容合并单元格的代码
- 同步器CountDownLatch的应用例子
- 基于AX88796B的网络接口模块的设计与实现
- 基于模板的树的接口定义及实现
- 基于FPGA的RS232串行接口的实现
- 基于XML的配置文件访问接口设计和实现
- 基于MATLAB 进行混合编程的接口技术实现
- 基于FPGA的以太网MII接口扩展设计与实现
- COM_001: 基于虚函数的接口实现,伪COM
- 基于Spring AOP实现对外接口的耗时监控
- 基于TCP/IP的SOCKET接口实现网络通信
- 基于ARM和DM9000的网卡接口设计与实现
- 2017年9月1日23:11:33
- HDU 1102 Constructing Roads(prim求最小生成树)
- Ubuntu uninstalling software completely(include purge configuration and files)
- [HDU]1520 Anniversary party
- JS直接修改CSS属性/id属性/class属性
- 基于同步器的合并接口实现
- 多线程编程1——基础知识
- EasyMall第十天
- druid 查询接口的使用
- PyCharm激活
- springboot学习一(环境搭建入门学习)
- Bigtable: A Distributed Storage System for Structured Data : part3 API
- TortoiseSVN设置比较工具为 Beyond Compare
- oracl 导出与导入字节码不一样 ORA-12899报错