限制Java的上传速度?

时间:2011-06-07 20:45:19

标签: java network-programming theory bandwidth-throttling

我想以编程方式限制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);
    }
}

以上代码是否有效?如果没有,有更好的方法吗?是否有描述该理论的教程?

3 个答案:

答案 0 :(得分:7)

Token Bucket Algorithm是一种限制上传或下载带宽的方法。 您应该阅读this article:它解释了此算法的使用。

使用Guava RateLimiter

// 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,你可以适应。