黑马程序员技术交流社区
标题:
多线程下载问题
[打印本页]
作者:
itpower
时间:
2014-1-24 22:28
标题:
多线程下载问题
如果没有加同步块虽然下载完毕的文件是正确的但是进度确实99%,加了同步块之后就是100%了。想了好几天没想出来到底是哪里出了同步问题。加法不应该会有同步问题啊?
package com.java.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class UpdateReceiver {
private static int length=0;
private RandomAccessFile accessFile;
private static Object object=new Object();
public static void main(String[] args) {
new UpdateReceiver().download("http://gdown.baidu.com/data/wisegame/3cf61f0c7216ed52/UCliulanqi_90.apk",3); // 开启三条线程进行文件的下载
}
/**
* 多线程下载文件
*
* @param path
* 网络文件URL
* @param threadNum
* 开启的线程数
*/
public void download(String path, int threadNum) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
if (conn.getResponseCode() == 200) {
int fileLength = conn.getContentLength(); // 获取网络文件大小
File file = new File("d://a", "b.exe");
accessFile = new RandomAccessFile(file, "rwd");
accessFile.setLength(fileLength); // 在本地生成相同大小的一个文件 }
int block = fileLength % threadNum == 0 ? fileLength/ threadNum : (fileLength / threadNum) + 1; // 每条线程负责下载的数据量
for (int threadId = 0; threadId < threadNum; threadId++) {
new DownloadThread(threadId, block, path, file).start();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class DownloadThread extends Thread {
private int threadId;
private int block;
private String path;
private File file;
public DownloadThread(int threadId, int block, String path, File file) {
this.threadId = threadId;
this.block = block;
this.path = path;
this.file = file;
}
public void run() {
super.run();
int start = threadId * block; // 计算线程从网络文件哪一处开始下载
int end = (threadId + 1) * block - 1; // 计算线程下载到网络文件的什么位置
InputStream in = null;
RandomAccessFile accessFile = null;
try {
accessFile = new RandomAccessFile(file, "rwd");
accessFile.seek(start);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);// 设置该头字段表示下载一部分数据
if (conn.getResponseCode() == 206) {// 请求范围时返回码应为206
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) != -1) {
synchronized (object) {
accessFile.write(buffer,0, len);
length+=len;
System.out.println(length*100/accessFile.length()+"%");
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
System.out.println("length:"+length);
System.out.println("第"+(threadId+1)+"条线程下载完毕");
if (accessFile != null && in != null) {
accessFile.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
复制代码
作者:
e.c
时间:
2014-1-29 21:50
synchronized (object) {
length+=len;
System.out.println(length*100/accessFile.length()+"%");
}
加锁只加在变量这里就可以了,文件操作不用。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2