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

トークンバケットアルゴリズムは、アップロードまたはダウンロードの帯域幅を制限する方法です。この記事を読む必要があります:このアルゴリズムの使用法について説明しています。

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)の呼び出しは、まったく同じスロットリングになります。 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 に答える