マルチスレッドダウンロードネットワークリソース
3978 ワード
複数のスレッドを作成すると、単位時間でより多くのサービス・エンド・リソースが得られ、ダウンロードが高速化されます.しかし、スレッドが多ければ多いほど良いわけではありません.クライアントに10000個のスレッドを新規作成すると、サービス側のCPUはオンラインスレッド間のポーリング切り替えに多くの時間を消費し、本当にデータリソースをダウンロードするのにかかる時間が減少します.また、クライアントとサービス側の物理帯域幅の制限により、ダウンロード速度も大きく関連します.
次に、ネットワーク上のリソースをマルチスレッドでダウンロードします.コードは次のとおりです.
十分な帯域幅がある場合、スレッドの個数を適切に増やせば、ダウンロードの速度が確実に速くなります.
次に、ネットワーク上のリソースをマルチスレッドでダウンロードします.コードは次のとおりです.
package hxl.insist.two;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
/**
*
* @author Hanxl
*/
public class MultiThreadDownload {
/**
*
*/
private int threadCount;
/**
* Url
*/
private String resourcePath;
/**
*
*/
private String fileName;
/**
* ,
*/
final CountDownLatch cdl = new CountDownLatch(threadCount);
public MultiThreadDownload(int threadCount,String resourcePath,String fileName) {
this.threadCount = threadCount;
this.resourcePath = resourcePath;
this.fileName = fileName;
}
/**
*
* @return
*/
private int createLocalFile() throws Exception {
URL url = new URL(resourcePath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Get
conn.setRequestMethod("GET");
//
conn.setConnectTimeout(5000);
//
int statusCode = conn.getResponseCode();
int resourceSize = 0;
if(statusCode == 200) {
//
resourceSize = conn.getContentLength();
//
RandomAccessFile localFile = new RandomAccessFile(fileName, "rw");
localFile.setLength(resourceSize);
}
return resourceSize;
}
/**
*
*/
private void createThreadAndDownload(final int startIndex,final int endIndex) {
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(resourcePath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//
conn.setRequestProperty("Range", "bytes=" + startIndex + "-"+endIndex);
//206
int code = conn.getResponseCode();
if(code == 206) {
RandomAccessFile localFile = new RandomAccessFile(fileName, "rw");
InputStream is = conn.getInputStream();
localFile.seek(startIndex);
System.out.println(Thread.currentThread().getName() + " : " + " " + startIndex + "---" + endIndex);
int len = -1;
byte[] bufferArea = new byte[1024];
while((len = is.read(bufferArea)) != -1) {
localFile.write(bufferArea, 0, len);
}
is.close();
localFile.close();
// , , 。
cdl.countDown();
System.out.println(Thread.currentThread().getName() + " : " + " ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}).start();
}
/**
*
*/
public void startDownload() throws Exception {
int resourceSize = createLocalFile();
if(resourceSize != 0) {
//
int resourceAverageSize = resourceSize / threadCount;
for(int threadIndex = 0;threadIndex < threadCount;threadIndex++) {
//
final int startIndex = threadIndex * resourceAverageSize;
int endIndex = startIndex + resourceAverageSize - 1;
if(threadIndex == (threadCount - 1)) {
endIndex = resourceSize - 1;
}
createThreadAndDownload(startIndex,endIndex);
}
}
while (true) {
//
cdl.await();
break;
}
}
public static void main(String[] args) {
try {
if(args.length == 3) {
MultiThreadDownload mtd = new MultiThreadDownload(Integer.parseInt(args[0]),args[1],args[2]);
mtd.startDownload();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
十分な帯域幅がある場合、スレッドの個数を適切に増やせば、ダウンロードの速度が確実に速くなります.