5

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

上面的代码会起作用吗?如果没有,有没有更好的方法来做到这一点?是否有描述该理论的教程?

4

3 回答 3

7

令牌桶算法是一种限制上传或下载带宽的方法。你应该阅读这篇文章:它解释了这个算法的使用。

使用番石榴速率限制器

// 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) 将导致完全相同的限制,如果any),但它会影响下一个请求的限制。即,如果一个昂贵的任务到达一个空闲的 RateLimiter,它会立即被授予,但它是下一个请求将经历额外的限制,从而支付昂贵任务的成本。

于 2011-06-07T21:43:56.633 回答
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();
    }
}

取决于 Guava,特别是 RateLimiter。

于 2014-09-25T16:04:22.317 回答
0

您需要某种方式让 isHittingLimit 知道在多长时间内传输了多少字节。在这个线程中有一个有趣的方法,你可以适应。

于 2011-06-07T20:52:26.587 回答