我想以编程方式限制Java中的上传或下载操作。我会假设我需要做的就是检查上传的速度,然后相应地插入Thread.sleep()
:
while (file.hasMoreLines()) {
String line = file.readLine();
for (int i = 0; i < line.length(); i+=128) {
outputStream.writeBytes(line.substr(i, i+128).getBytes());
if (isHittingLimit())
Thread.sleep(500);
}
}
以上代码是否有效?如果没有,有更好的方法吗?是否有描述该理论的教程?
答案 0 :(得分:7)
Token Bucket Algorithm是一种限制上传或下载带宽的方法。 您应该阅读this article:它解释了此算法的使用。
// rate = 512 permits per second or 512 bytes per second in this case
final RateLimiter rateLimiter = RateLimiter.create(512.0);
while (file.hasMoreLines()) {
String line = file.readLine();
for (int i = 0; i < line.length(); i+=128) {
byte[] bytes = line.substr(i, i+128).getBytes();
rateLimiter.acquire(bytes.length);
outputStream.writeBytes(bytes);
}
}
如Guava文档中所述: 重要的是要注意,请求的许可数量永远不会影响请求本身的限制(对acquire(1)的调用和对acquire(1000)的调用将导致完全相同的限制,如果有的话),但它会影响下一个请求的限制。即,如果一个昂贵的任务到达空闲的RateLimiter,它将立即被授予,但它是下一个将经历额外限制的请求,从而支付昂贵任务的成本。
答案 1 :(得分:1)
这是一篇很老的帖子,但是这个怎么样:
import com.google.common.util.concurrent.RateLimiter;
import java.io.IOException;
import java.io.OutputStream;
public final class ThrottledOutputStream extends OutputStream {
private final OutputStream out;
private final RateLimiter rateLimiter;
public ThrottledOutputStream(OutputStream out, double bytesPerSecond) {
this.out = out;
this.rateLimiter = RateLimiter.create(bytesPerSecond);
}
public void setRate(double bytesPerSecond) {
rateLimiter.setRate(bytesPerSecond);
}
@Override
public void write(int b) throws IOException {
rateLimiter.acquire();
out.write(b);
}
@Override
public void write(byte[] b) throws IOException {
rateLimiter.acquire(b.length);
out.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
rateLimiter.acquire(len);
out.write(b, off, len);
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void close() throws IOException {
out.close();
}
}
取决于番石榴,特别是RateLimiter。
答案 2 :(得分:0)
你需要一些方法让isHittingLimit知道多长时间内传输了多少字节。有一种有趣的方法in this thread,你可以适应。