我从一个管理所有下载的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秒)内可以读取多少字节的计数器.每次读取调用都会检查计数器并使用它来限制读取的实际字节数.计时器用于重置计数器.
实际上,在多个流中分配带宽可能会变得相当复杂,特别是为了避免饥饿和促进公平,但这应该给你一个公平的开始.