package org.kne.cloud.network; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; import java.util.function.LongUnaryOperator; import java.util.function.UnaryOperator; public class SpeedLimiter { public boolean isHitlimit() { return hitlimit; } private volatile long limitspeed=1024*1024; private long brustTime=2000000L; private volatile boolean hitlimit=false; public long getLimitspeed() { return limitspeed; } public SpeedLimiter(long limitspeed) { super(); this.limitspeed = limitspeed; } public SpeedLimiter(long limitspeed, long brustTime) { super(); this.limitspeed = limitspeed; this.brustTime = brustTime; } public void setLimitspeed(long limitspeed) { this.limitspeed = limitspeed; //System.out.println("更新限速:"+limitspeed); } public long getBrustTime() { return brustTime; } public void setBrustTime(long brustTime) { this.brustTime = brustTime; } private AtomicLong ltime=new AtomicLong( System.nanoTime()); private AtomicLong waitingtime=new AtomicLong(); @Override public String toString() { return "SpeedLimiter [limitspeed=" + limitspeed + ", brustTime=" + brustTime + ", hitlimit=" + hitlimit + ", ltime=" + ltime + ", waitingtime=" + waitingtime + "]"; } public void forceTransmit(long datasize) { long limitspeedx=limitspeed; if(limitspeedx>0) { long curtime=System.nanoTime(); long pasttime=ltime.getAndSet(curtime); long nv=waitingtime.updateAndGet(new LongUnaryOperator() { @Override public long applyAsLong(long t) { t-=curtime-pasttime; if(t<0L) t=0L; return t; } }); waitingtime.addAndGet((long) (datasize*1000000000.0/limitspeedx)); } } //用系统计时器的时刻相减得到经过的时间,与数据包除以限速值得到的应消耗的时间做对比,若时间还未到达发送下一个数据包的时机,则返回false public boolean checkTransmit(long datasize) { long limitspeedx=limitspeed; if(limitspeedx<=0) { return false; } long curtime=System.nanoTime(); long pasttime=ltime.getAndSet(curtime); long nv=waitingtime.updateAndGet(new LongUnaryOperator() { @Override public long applyAsLong(long t) { t-=curtime-pasttime; if(t<0L) t=0L; return t; } }); if(nv<=brustTime) { return true; }else { return false; } } public void transmit(long datasize) { long limitspeedx=limitspeed; while(!checkTransmit(datasize)) { //LockSupport.parkNanos(100000); Thread.yield(); } waitingtime.addAndGet((long) (datasize*1000000000.0/limitspeedx)); } }