Ограничение скорости загрузки на Java? - PullRequest
5 голосов
/ 08 июня 2011

Я бы хотел программно ограничить операции загрузки или выгрузки в 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 ]

7 голосов
/ 08 июня 2011

Алгоритм Token Bucket - это способ ограничения загрузки или пропускной способности загрузки. Вы должны прочитать эту статью : она объясняет использование этого алгоритма.

Использование 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: Важно отметить, что количество запрошенных разрешений никогда не влияет на регулирование самого запроса (вызов для получения (1) и вызов для получения (1000) приведут к точно такой же регулировке, если таковые имеются), но это влияет на удушение следующего запроса. То есть, если дорогостоящее задание прибывает в незанятый RateLimiter, оно будет предоставлено немедленно, но это следующий запрос, который будет испытывать дополнительное удушение, таким образом оплачивая стоимость дорогого задания.

1 голос
/ 25 сентября 2014

Это старый пост, но как насчет этого:

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.

0 голосов
/ 08 июня 2011

Вам понадобится какой-то способ для isHittingLimit, чтобы узнать, сколько байтов было передано в течение какого времени. Есть интересный подход в этой теме , который вы можете адаптировать.

...