為父母生,為老婆死,為程序奮斗一輩子,吃眼前虧,上公司的當(dāng),最后死在客戶的需求上

          Hector_封嘴

          華子說:看破紅塵,與程序為伴!
          posts - 4, comments - 1, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Java多線程下載文件

          Posted on 2012-10-23 06:52 赫赫 閱讀(286) 評論(0)  編輯  收藏 所屬分類: J2EE
          文件下載采用多線程方式能夠充分利用CPU資源,關(guān)鍵點是設(shè)置線程的讀取開始和結(jié)束位置。下面的代碼,采用線程池啟動10個線程來執(zhí)行下載
          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");
                  
          //計算每個線程請求文件的開始和結(jié)束位置
                  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();
                          
                      }

                  }

              }

          }


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          用兩年的工作經(jīng)驗,從零開始,重新開始做一個稱職的程序員!
          主站蜘蛛池模板: 江西省| 攀枝花市| 中牟县| 涟水县| 泰州市| 集贤县| 虞城县| 车致| 息烽县| 镇原县| 成安县| 松桃| 吐鲁番市| 高淳县| 乌海市| 克山县| 枣强县| 宝丰县| 湖北省| 北辰区| 新巴尔虎左旗| 梁山县| 鄂托克前旗| 监利县| 长白| 永顺县| 昌吉市| 沂源县| 香格里拉县| 安徽省| 信宜市| 黔南| 五大连池市| 丁青县| 铁岭县| 厦门市| 衡阳县| 剑川县| 都江堰市| 临夏县| 龙陵县|