import java.io.*;
import java.net.*;
public class URLConnectionDemo{
public static void main(String[] args)throws Exception{
String path="http://127.0.0.1:8080/myweb/jianli_1.jpg";
int threadNum=4;
URL url=new URL(path);
URLConnection conn=(HttpURLConnection)url.openConnection();
RandomAccessFile currentPart=new RandomAccessFile("jianli_2.jpg","rw");
int fileSize=conn.getContentLength();
int startpo=0;
int currentSize=fileSize/threadNum;
for(int i=0;i<threadNum;i++)
{
new DownThread(path,startpo,currentSize,currentPart).start();
startpo=currentSize*i+1;
}
}
}
class DownThread extends Thread{
private String path;
private int startpo;
private int currentSize;
private int length;
private RandomAccessFile currentPart;
public DownThread(String path,int startpo,int currentSize,RandomAccessFile currentPart){
this.path=path;
this.startpo=startpo;
this.currentSize=currentSize;
this.currentPart=currentPart;
   }
public void run(){
try{
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept","image/jpeg,image/gif,image/pjpeg,image/pjpeg,application/x-shockwave-flash,*/*");
conn.setRequestProperty("Accept-language","zh-CN");
conn.setRequestProperty("Charset","UTF-8");
InputStream is=conn.getInputStream();
is.skip(this.startpo);
byte[] buf=new byte[1024];
int len=0;
while((len=is.read(buf))!=-1&&length<currentSize)
{
currentPart.seek(startpo);
currentPart.write(buf,0,len);
length+=len;

}
}
catch(Exception e){

}
}}

解决方案 »

  1.   

    应该是写文件的时候没有互斥,多个线程同时向一个文件写入数据的话,文件指针可以被到处移动导致写入的位置不是预期的。
     将下面的代码用synchronized括起来试试:while((len=is.read(buf))!=-1&&length<currentSize)
        {
            currentPart.seek(startpo);
            currentPart.write(buf,0,len);
            length+=len;
             
        }
      

  2.   

    至少  length 这个属性会被多个线程进行共享修改 
      

  3.   

    先不说楼上几位说的代码里的多线程互斥问题,就说你的下载逻辑多线程下载,下载的都是同一个文件的同一段,然后又写到同一个文件里去,当然会出现问题。多线程下载的实现原理是 每个线程下载服务器上文件的某一段,如文件是100M,5线程下载
    线程一是0-20M
    线程二是20M-40M
    依次类推而你的代码里显然没有这样的逻辑tips,下载服务器上文件的某一段,是用Range的header做的。