http://blog.csdn.net/houjixin/article/details/45222081 或者
http://houjixin.blog.163.com/blog/static/3562841020153233201796/
中实现的限速器,需要内部维持一个容器来记录每次访问的时间,在每次新请求资源时通过计算容器中首尾两个时间的差值以及容器中的访问次数来确定是否超速,其实这种实现方法有两个缺点:
(1)只比较了平均速度,没有比较瞬时速度,假如限速器限制每秒钟最多访问1000次,如果前500毫秒访问了999次,后500毫秒就访问一次,这种情况就无法进行判断;
(2)实现方法比较复杂。
因此,在本文中实现的是基于间隔时间的限速方法,它的基本思路为:假如限速器限制的最大访问速度为每秒100,则可认为,相邻两次访问的间隔时间不能小于10毫秒,因此,在每次访问资源时只需要比较与上次访问的时间间隔即可,相关实现代码为:

package test_tmp;import java.util.concurrent.Semaphore;
//使用两次相邻使用的间隔时间进行判断
import java.util.concurrent.atomic.AtomicLong;
public class SpeedLimiter2<T> {private static long INIT_TIME = 0;//参数maxUsedFrequency,表示对资源resource的最大访问速度为每秒maxUsedFrequency次public SpeedLimiter2(int maxUsedFrequency, T resource){this.resource = resource;this.interval = 1000 / maxUsedFrequency;//表示相邻两次之间的访问间隔时间(毫秒)m_semaphore = new Semaphore(maxUsedFrequency);lastUsedTime = new AtomicLong(INIT_TIME);}private AtomicLong lastUsedTime = null;private long interval = 0;//相邻两次申请资源的最大间隔时间private T resource = null;//用信号量来限制资源的访问private Semaphore m_semaphore = null;//同步申请资源public synchronized T consume(){long curTime = System.currentTimeMillis();long curInterVal = curTime - lastUsedTime.get();if(curInterVal < interval){//请求速度太快了,需要休息一下System.out.println(String.format("+++++++++++++++need sleep: interval:%d - %d = %d",interval,  curInterVal, (interval - curInterVal)));safeSleep(interval - curInterVal);}//申请资源try {m_semaphore.acquire();} catch (InterruptedException e) {e.printStackTrace();return null;}lastUsedTime.getAndSet(System.currentTimeMillis());//记录下申请资源成功的时间return resource;}public void returnResource(){System.out.println("-------------回收一个资源");m_semaphore.release();}private void safeSleep(long sleepTime){try{Thread.sleep(sleepTime);}catch (InterruptedException e){e.printStackTrace();}}}

相关的测试线程的代码为:

package test_tmp;public class TestSpeedLimitedThread2<T> extends Thread {SpeedLimiter2<T> limiter = null;public TestSpeedLimitedThread2(SpeedLimiter2<T> limiter){this.limiter = limiter;}public void run(){long i = 0;while(true){T tmpResource = limiter.consume();System.out.println("thread id: " + currentThread().getId() + " : " +(i+1) + ": 已经获取到资源:" + tmpResource);i++;try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}limiter.returnResource();}}
}

相关的主测试代码为:

    public static void  testSpeedLimiter(){String resource = "myresource";SpeedLimiter2<String> test = new SpeedLimiter2<String>(50, resource);TestSpeedLimitedThread2<String> testThread1 = new TestSpeedLimitedThread2<String>(test);testThread1.start();TestSpeedLimitedThread2<String> testThread2 = new TestSpeedLimitedThread2<String>(test);testThread2.start();TestSpeedLimitedThread2<String> testThread3 = new TestSpeedLimitedThread2<String>(test);testThread3.start();try {testThread1.join();testThread2.join();testThread3.join();} catch (InterruptedException e) {e.printStackTrace();}}

特别注意:
上述的限速器在限速上限1000以下时都能正常工作,如果上限大于1000,则需要使用微妙来计算;

一个简单限速器的java实现[2]相关推荐

  1. 一个简单限速器的java实现[1]

    在日常开发过程中,经常遇到对资源使用频度的限制,例如:某个接口只允许每秒调用300次,或者某个资源对象只允许每秒使用300等等,下面是一个简单的限速器的java实现,它可以实现对一个资源在若干时间(毫 ...

  2. 一个简单的例子看java线程机制

    一个简单的例子看java线程机制 作者: zyf0808 发表日期: 2006-03-26 11:20 文章属性: 原创 复制链接 import java.util.*; public class T ...

  3. java继承类型转换_#java 一个简单的例子理解java继承、成员函数重写、类型转换...

    一个简单的例子理解java继承.成员函数重写.类型转换 1.继承简介 举一个简单的例子:笔分为很多种,比如毛笔.钢笔.圆珠笔等等,这些笔都有一些相同的属性比如长度.笔迹的粗细等等:但他们也有不同的特点 ...

  4. 如何用FFmpeg编写一个简单播放器详细步骤介绍

    如何用FFmpeg编写一个简单播放器详细步骤介绍(转载) FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码.复用和解复用. ...

  5. 如何用 FFmpeg 编写一个简单播放器.pdf

    An ffmpeg and SDL Tutorial.pdf 如何用 FFmpeg 编写一个简单播放器.pdf 中文版

  6. Verilog——一个简单仲裁器的实现

    Verilog--一个简单仲裁器的实现 仲裁器基本功能 仲裁器(arbiter) 的主要功能是,多个source源同时发出请求时,根据当前的优先级来判断应响应哪一个source. 仲裁器分为轮询优先级 ...

  7. python批量下载文件只有1kb_详解如何用python实现一个简单下载器的服务端和客户端...

    话不多说,先看代码: 客户端: import socket def main(): #creat: download_client=socket.socket(socket.AF_INET,socke ...

  8. 【javamatlab】以一个简单的例子实现java和matlab混编

    目录 使用环境: MATLAB: matlab代码: 将matlab代码打包: eclipse: jar包配置: 使用jar包: 使用环境: jdk8(ide使用eclipse2019-6).matl ...

  9. FFmpeg编写一个简单播放器 -1

    2019独角兽企业重金招聘Python工程师标准>>> 指导1:制作屏幕录像 概要   电影文件有很多基本的组成部分.首先,文件本身被称为容器Container,容器的类型决定了信息 ...

最新文章

  1. 配置Keil C51配置开发 STC51单片机过程
  2. 洛谷P1433 吃奶酪【dfs】【剪枝】
  3. Radware:2016年攻击趋势
  4. hdu2561 第二小整数(排序)
  5. P2048 [NOI2010]超级钢琴
  6. cookie和session原理
  7. oracle查看表的命令,Oracle常用查看表结构命令
  8. 哈师大计算机等级考试,哈尔滨师范大学教务处
  9. pointcut 排除_宁河天津玻璃门地弹簧玻璃门故障排除
  10. kettle工具的设计原则
  11. mysql join 组合索引,图文详解MySQL中两表关联的连接表如何创建索引
  12. Git使用笔记[持续更新]
  13. 2018-07-29 Sun. 随机取名byD大
  14. html手机和电脑一致,浏览器兼容性(手机、电脑。js、html、css)
  15. 第二课 IDEA 的使用
  16. 支持JSP和Servlet的Web服务器
  17. OpenDaylight-Boron学习笔记: 3 L2Switch模块
  18. 有关计算机知识的活动总结,计算机兴趣小组活动总结范文
  19. kali linux连不上网,NAT模式静态ip解决问题
  20. 2021【敏捷CSM认证】Sprint回顾会议-检视工作,提升效率

热门文章

  1. WORD样式保存为主题集?
  2. 创建选修专业表oracle,数据库及数据表的创建与删除 (Oracle实验)
  3. EmEditor18.1.2 注册码
  4. A Scala Tutorial for Java programmers之(一)Scala入门:Scala例子,以及如何与Java交互
  5. mybatis case when_MyBatis 几种通用的写法
  6. python中画圆的代码_Python使用matplotlib绘制圆形代码实例
  7. python解码函数_Python字符串中的两个解码与解码函数详解
  8. 长沙城南学院的计算机科学,长沙理工大学城南学院计算机科学与技术专业2016年在云南理科高考录取最低分数线...
  9. python pca降维_MLK | 机器学习的降维quot;打击quot;
  10. mysql监控sql_如何实时监控mysql中的SQL语句的执行情况