问一个有难度的问题!如何限制一个函数在多线程环境中被调用的频率?

keios 2004-07-19 03:33:39
比如我希望一个函数在多线程环境中只能每秒被调用10次,多于10次后续的调用将被阻塞,等到下一秒才执行。
如何实现?请各位谈谈想法。
...全文
454 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
keios 2004-07-20
  • 打赏
  • 举报
回复
呵呵,乘除也就是一条CPU指令,执行周期长些而已,
而创建对象再被垃圾回收耗费的资源可比这个多多了 ^o^
其实 taolei(实在无聊) 说的也对,有时没必要在这些小地方花费太多心思。
多谢各位
moonyuezhao 2004-07-20
  • 打赏
  • 举报
回复
说错了,刚才没仔细看

不过既然你要考虑效率,可以不用乘除的尽量不要用
moonyuezhao 2004-07-20
  • 打赏
  • 举报
回复
说错了,刚才没仔细看

不过既然你要考虑效率,可以不用乘除的尽量不要用
moonyuezhao 2004-07-20
  • 打赏
  • 举报
回复
to:keios(每天跑5圈)

要那么多的除法干吗,两个数不除不是照样比较
javafaq2004 2004-07-20
  • 打赏
  • 举报
回复
好象已经解决
keios 2004-07-20
  • 打赏
  • 举报
回复
在函数入口调用 sync.acquire();
实现的方法同 zhujj81(编程、游戏两不误) 说的类似:

public class FrequencyCallerSync {

private final int frequency; //(execute per sec)

private volatile long lastSec;
private int lastCalled;

public FrequencyCallerSync(int freq) {
this.frequency = freq;
lastSec = System.currentTimeMillis() / 1000;
lastCalled = 0;
}

public synchronized void acquire() throws java.lang.InterruptedException {

long nowTm = System.currentTimeMillis();
long nowSec = nowTm / 1000;
while ( (nowSec == lastSec)
&& (lastCalled >= frequency)) {
Thread.sleep(nowTm % 1000);
nowTm = System.currentTimeMillis();
nowSec = nowTm / 1000;
}

if (nowSec == lastSec) {
lastCalled++;
}
else {
lastSec = nowSec;
lastCalled = 1;
}
}

}
ChDw 2004-07-20
  • 打赏
  • 举报
回复
使用Tomcat之类的连接池,设定最大的数目setMaxTotal();
进入方法从池中拿一个对象(new Object()就可以了),然后在退出方法时再返回到连接池中
这样只要到达最大数目,后面的请求就会在等正在处理的请求完成以后才能进入了
moonyuezhao 2004-07-20
  • 打赏
  • 举报
回复
其实 taolei(实在无聊) 说的也对,有时没必要在这些小地方花费太多心思。

-----

呵呵,这句话是仁者见仁,智者见智拉,我觉得做程序员的乐趣就在这些方面才能体现,否则,大家都能做的事情做的再多,也没多少意思
zhujj81 2004-07-19
  • 打赏
  • 举报
回复
比较经典的话题,我个人比较喜好Thread.sleep()的做法。

但我没有想通的就是:为什么不能把一个时间计数值和每秒钟的调用次数作为临界资源呢?若一秒调用次数超过10,则Thread.sleep();否则继续分配。这样做的好处就是避免了调用的等待太长的时间。

个人意见,仅供参考。
moonyuezhao 2004-07-19
  • 打赏
  • 举报
回复
1)
不是那么简单的,比如信号量,信号值设为多少合适?
---
当另外一个信号量的值为1是的系统时间

2)
回复人:rick_silver(杨若蝉) ( 三级(初级)) 信誉:94 2004-07-19 16:40:00 得分:0
将被调用方法声明为synchronized,而后在程序逻辑执行完毕后,执行Thread.sleep(100),这样,在十分之一秒内没有别的线程可以调用它了
这样可以么?
----
觉得这个想法不错,当信号量的值为10时,Thread.sleep(),结束后将信号量的值设为0
taolei 2004-07-19
  • 打赏
  • 举报
回复
keios(每天跑5圈):
比起你的其他程序,或者JDBC、EJB等,Vector还是LinkedList或者其他的什么方法根本就算不上什么问题
没必要在这个问题上花更多的心思
keios 2004-07-19
  • 打赏
  • 举报
回复
to taolei(实在无聊)
你的方法很好!非常感谢!
但是我觉得它还有一些缺陷:
1.它的内存占用比较大,如果我的_cps是几十或者上百,则它会保存这么多个Long对象。
2.效率,对于需要尾部添加首部删除的容器,我会使用 LinkedList 而不是 Vector。
再次感谢你激发了我的灵感。
其他人还有更好的方法吗?
taolei 2004-07-19
  • 打赏
  • 举报
回复
TimeLimiter tl = new TimeLimiter(10);
在函数入口调用 tl.invoke();就行了
public class TimeLimiter
{
private int cps;
private java.util.Vector times = new java.util.Vector();
public TimeLimiter(int _cps)
{
cps = _cps;
}
public synchronized void invoke()
{
long t = System.currentTimeMillis();
if (times.size()==cps)
{
long t0 = ((Long)times.remove(0)).longValue();
long w = 1000L-(t-t0);
if(w>=0)
{
try
{
Thread.sleep(w);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
times.addElement(new Long(t));
}
}
rick_silver 2004-07-19
  • 打赏
  • 举报
回复
将被调用方法声明为synchronized,而后在程序逻辑执行完毕后,执行Thread.sleep(100),这样,在十分之一秒内没有别的线程可以调用它了
这样可以么?
keios 2004-07-19
  • 打赏
  • 举报
回复
不是那么简单的,比如信号量,信号值设为多少合适?

函数的执行也是需要时间的,甚至会需要若干秒。
当然我只需在函数的入口控制频度即可,出函数可以不管。
tanghuan 2004-07-19
  • 打赏
  • 举报
回复
用同步机制加信号量
moonyuezhao 2004-07-19
  • 打赏
  • 举报
回复
增加二个标志(都应该是同步资源),一个用户表示当前秒所调用的次数,另一个用来记录时间

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧