Простое решение путем создания ThrottledInputStream.
Это следует использовать так:
final InputStream slowIS = new ThrottledInputStream(new BufferedInputStream(new FileInputStream("c:\\file.txt"),8000),300);
300 - это количество килобайт в секунду. 8000 - это размер блока для BufferedInputStream.
Это, конечно, следует обобщить путем реализации read (byte b [], int off, int len), который избавит вас от тонны вызовов System.currentTimeMillis (). System.currentTimeMillis () вызывается один раз для каждого считанного байта, что может привести к небольшим издержкам. Также должно быть возможно сохранить количество байтов, которые можно безопасно прочитать без вызова System.currentTimeMillis ().
Не забудьте поместить BufferedInputStream между ними, в противном случае FileInputStream будет опрашиваться отдельными байтами, а не блоками. Это снизит нагрузку CPU с 10% до почти 0. Вы рискуете превысить скорость передачи данных на количество байтов в размере блока.
import java.io.InputStream;
import java.io.IOException;
public class ThrottledInputStream extends InputStream {
private final InputStream rawStream;
private long totalBytesRead;
private long startTimeMillis;
private static final int BYTES_PER_KILOBYTE = 1024;
private static final int MILLIS_PER_SECOND = 1000;
private final int ratePerMillis;
public ThrottledInputStream(InputStream rawStream, int kBytesPersecond) {
this.rawStream = rawStream;
ratePerMillis = kBytesPersecond * BYTES_PER_KILOBYTE / MILLIS_PER_SECOND;
}
@Override
public int read() throws IOException {
if (startTimeMillis == 0) {
startTimeMillis = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long interval = now - startTimeMillis;
//see if we are too fast..
if (interval * ratePerMillis < totalBytesRead + 1) { //+1 because we are reading 1 byte
try {
final long sleepTime = ratePerMillis / (totalBytesRead + 1) - interval; // will most likely only be relevant on the first few passes
Thread.sleep(Math.max(1, sleepTime));
} catch (InterruptedException e) {//never realized what that is good for :)
}
}
totalBytesRead += 1;
return rawStream.read();
}
}