为父母生,为老婆死,为程序奋斗一辈子,吃眼前亏,上公司的当,最后死在客户的需求上

Hector_封嘴

华子说:看破红尘,与程序为伴!
posts - 4, comments - 1, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Java多线程下载文件

Posted on 2012-10-23 06:52 赫赫 阅读(275) 评论(0)  编辑  收藏 所属分类: J2EE
文件下载采用多线程方式能够充分利用CPU资源,关键点是设置线程的读取开始和结束位置。下面的代码,采用线程池启动10个线程来执行下载
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class FileDownLoadTest {
    
    
    
private static final int TCOUNT = 10;
    
    
private CountDownLatch latch = new CountDownLatch(TCOUNT);

    
private long completeLength = 0;
    
    
private long fileLength;
    
/**
     * 
@param args
     * 
@throws Exception 
     
*/

    
public static void main(String[] args) throws Exception {
        
        
new FileDownLoadTest().download("http://localhost:8080/test/IESSAction.docx");
    }

    
    
    
public void download(String address) throws Exception{
        ExecutorService service 
= Executors.newFixedThreadPool(TCOUNT);
        URL url 
= new URL(address);
        URLConnection cn 
= url.openConnection();
        cn.setRequestProperty(
"Referer""http://www.test.com");
        fileLength 
= cn.getContentLength();
        
long packageLength = fileLength/TCOUNT;
        
long leftLength = fileLength%TCOUNT;
        RandomAccessFile file 
= new RandomAccessFile("d:\\test.docx","rw");
        
//计算每个线程请求文件的开始和结束位置
        long pos = 0;
        
long endPos = pos + packageLength;
        
for(int i=0; i<TCOUNT; i++){
            
if(leftLength >0){
                endPos 
++;
                leftLength
--;
            }

            service.execute(
new DownLoadThread(url, file, pos, endPos));
            pos 
= endPos;
            endPos 
= pos + packageLength;
        }

        System.out.println(
"waiting.");
        
long begin = System.currentTimeMillis();
        latch.await();
        file.close();
        System.out.println(
"end.");
        System.out.println(System.currentTimeMillis() 
- begin + "ms");
        service.shutdown();
    }

    
    
class DownLoadThread implements Runnable{
        
        
private URL url;
        
private RandomAccessFile file;
        
private long from;
        
private long end;
        
        DownLoadThread(URL url, RandomAccessFile file, 
long from, long end){
            
this.url = url;
            
this.file = file;
            
this.from = from;
            
this.end = end;
        }

        
        
        
public void run() {
            
long pos = from;
            
byte[] buf = new byte[512];
            
try {
                HttpURLConnection cn 
= (HttpURLConnection) url.openConnection();
                cn.setRequestProperty(
"Range""bytes=" + from + "-" + end);
                
if(cn.getResponseCode() != 200 && cn.getResponseCode()!=206){
                    run();
                    
return;
                }

                BufferedInputStream bis 
= new BufferedInputStream(cn.getInputStream());
                
int len ;
                
while((len = bis.read(buf)) != -1){
//                    synchronized(file){
                        file.seek(pos);
                        file.write(buf, 
0, len);
//                    }
                    pos += len;
                    completeLength 
+=len;
                    System.out.println(
"threadName: " + Thread.currentThread().getName() 
                            
+ "persent: " + completeLength * 100 /fileLength + "%");
                }

                cn.disconnect();
                latch.countDown();
            }
 catch (IOException e) {
                e.printStackTrace();
                
            }

        }

    }

}


只有注册用户登录后才能发表评论。


网站导航:
 
用两年的工作经验,从零开始,重新开始做一个称职的程序员!