Я бы начал с DownloadManager, который управляет всеми загрузками.
interface DownloadManager
{
public InputStream registerDownload(InputStream stream);
}
Весь код, который хочет принять участие в управляемой полосе пропускания, зарегистрирует свой поток в менеджере загрузок, прежде чем начнет читать из него. В своем методе registerDownload () менеджер упаковывает данный поток ввода в ManagedBandwidthStream
.
public class ManagedBandwidthStream extends InputStream
{
private DownloadManagerImpl owner;
public ManagedBandwidthStream(
InputStream original,
DownloadManagerImpl owner
)
{
super(original);
this.owner = owner;
}
public int read(byte[] b, int offset, int length)
{
owner.read(this, b, offset, length);
}
// used by DownloadManager to actually read from the stream
int actuallyRead(byte[] b, int offset, int length)
{
super.read(b, offset, length);
}
// also override other read() methods to delegate to the read() above
}
Поток гарантирует, что все вызовы read () будут направлены обратно в менеджер загрузок.
class DownloadManagerImpl implements DownloadManager
{
public InputStream registerDownload(InputStream in)
{
return new ManagedDownloadStream(in);
}
void read(ManagedDownloadStream source, byte[] b, int offset, int len)
{
// all your streams now call this method.
// You can decide how much data to actually read.
int allowed = getAllowedDataRead(source, len);
int read = source.actuallyRead(b, offset, len);
recordBytesRead(read); // update counters for number of bytes read
}
}
Ваша стратегия распределения пропускной способности заключается в том, как реализовать getAllowedDataRead ().
Простой способ регулирования пропускной способности:
сохраняйте счетчик того, сколько еще байтов может быть прочитано за данный период (например, 1 секунда). Каждый вызов read проверяет счетчик и использует его для ограничения фактического количества прочитанных байтов. Таймер используется для сброса счетчика.
На практике распределение полосы пропускания между несколькими потоками может быть довольно сложным, особенно во избежание голода и содействия справедливости, но это должно дать вам справедливое начало.