2011-06-07 64 views
5

我想以編程方式限制Java中的上傳或下載操作。我將承擔所有我需要做的就是做檢查上載有多快,並插入相應Thread.sleep()像這樣:限制Java的上傳速度?

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); 
    } 
} 

請問上面的代碼工作?如果沒有,有沒有更好的方法來做到這一點?有沒有描述理論的教程?

+0

這可能會減慢上/下載率。儘管取決於在每次迭代中發送的數據量以及睡眠週期的長度,但可能難以精確限制(即,連接速度將改變但不清楚多少)。爲了更好地進行調整,理論上你會希望減少在每次迭代中發送的數據量(例如從一行到一個字符)以及在限制被打時花費的時間。這應該會導致更頻繁和更精細的調整...不張貼爲答案,因爲我沒有教程,並沒有驗證它。 – gnomed 2011-06-07 20:51:18

+0

另外:使用Reader也不是一個好主意,也不是逐行讀取,因爲您基本上是將字節(UTF-8等)中的數據解碼爲字符,然後重新編碼,取出一些字節,放下其他字節。而是從InputStream中讀取一定數量的字節,發送這些字節,並避免在這裏不需要的解碼/編碼。 – StaxMan 2011-06-07 23:49:20

回答

6

Token Bucket Algorithm是一種限制上傳或下載帶寬的方法。 您應該閱讀this article:它解釋了這種算法的使用。

使用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); 
    } 
} 

如番石榴文檔解釋說: 需要注意的是許可證的數量要求從不影響請求本身(調用獲取(1)與節流很重要調用獲取(1000)將導致完全相同的調節,如果有的話),但它會影響下一個請求的調節。也就是說,如果一個昂貴的任務到達一個空閒的RateLimiter,它將被立即授予,但是它是下一個請求會經歷額外的限制,從而支付昂貴任務的成本。

+0

https://github.com/bbeck/token-bucket實施 – kervin 2015-08-09 16:48:09

0

你需要一些方法讓isHittingLimit知道有多少字節已經傳輸了多長時間。有一個有趣的方法in this thread,你可能會適應。

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(); 
    } 
} 

取決於番石榴,特別是RateLimiter。