A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© itpower 高级黑马   /  2014-1-24 22:28  /  1538 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

如果没有加同步块虽然下载完毕的文件是正确的但是进度确实99%,加了同步块之后就是100%了。想了好几天没想出来到底是哪里出了同步问题。加法不应该会有同步问题啊?






  1. package com.java.test;

  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.RandomAccessFile;
  7. import java.net.HttpURLConnection;
  8. import java.net.MalformedURLException;
  9. import java.net.URL;

  10. public class UpdateReceiver {
  11.         private static int length=0;
  12.         private RandomAccessFile accessFile;
  13.         private static Object object=new Object();
  14.         public static void main(String[] args) {
  15.                 new UpdateReceiver().download("http://gdown.baidu.com/data/wisegame/3cf61f0c7216ed52/UCliulanqi_90.apk",3); // 开启三条线程进行文件的下载
  16.         }

  17.         /**
  18.          * 多线程下载文件
  19.          *
  20.          * @param path
  21.          *            网络文件URL
  22.          * @param threadNum
  23.          *            开启的线程数
  24.          */
  25.         public void download(String path, int threadNum) {
  26.                 try {
  27.                         URL url = new URL(path);
  28.                         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  29.                         conn.setConnectTimeout(3000);
  30.                         conn.setRequestMethod("GET");
  31.                         if (conn.getResponseCode() == 200) {
  32.                                 int fileLength = conn.getContentLength(); // 获取网络文件大小
  33.                                 File file = new File("d://a", "b.exe");
  34.                                 accessFile = new RandomAccessFile(file, "rwd");
  35.                                 accessFile.setLength(fileLength); // 在本地生成相同大小的一个文件 }
  36.                                 int block = fileLength % threadNum == 0 ? fileLength/ threadNum : (fileLength / threadNum) + 1; // 每条线程负责下载的数据量
  37.                                 for (int threadId = 0; threadId < threadNum; threadId++) {
  38.                                         new DownloadThread(threadId, block, path, file).start();
  39.                                 }
  40.                         }
  41.                 } catch (MalformedURLException e) {
  42.                         e.printStackTrace();
  43.                 } catch (IOException e) {
  44.                         e.printStackTrace();
  45.                 }
  46.         }

  47.         public class DownloadThread extends Thread {
  48.                 private int threadId;
  49.                 private int block;
  50.                 private String path;
  51.                 private File file;

  52.                 public DownloadThread(int threadId, int block, String path, File file) {
  53.                         this.threadId = threadId;
  54.                         this.block = block;
  55.                         this.path = path;
  56.                         this.file = file;
  57.                 }

  58.                 public void run() {
  59.                         super.run();
  60.                         int start = threadId * block; // 计算线程从网络文件哪一处开始下载
  61.                         int end = (threadId + 1) * block - 1; // 计算线程下载到网络文件的什么位置
  62.                         InputStream in = null;
  63.                         RandomAccessFile accessFile = null;
  64.                         try {
  65.                                 accessFile = new RandomAccessFile(file, "rwd");
  66.                                 accessFile.seek(start);
  67.                                 URL url = new URL(path);
  68.                                 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  69.                                 conn.setConnectTimeout(3000);
  70.                                 conn.setRequestMethod("GET");
  71.                                 conn.setRequestProperty("Range", "bytes=" + start + "-" + end);// 设置该头字段表示下载一部分数据
  72.                                 if (conn.getResponseCode() == 206) {// 请求范围时返回码应为206
  73.                                         in = conn.getInputStream();
  74.                                         byte[] buffer = new byte[1024];
  75.                                         int len = 0;
  76.                                         while ((len = in.read(buffer)) != -1) {
  77.                                                 synchronized (object) {
  78.                                                         accessFile.write(buffer,0, len);
  79.                                                         length+=len;
  80.                                                         System.out.println(length*100/accessFile.length()+"%");
  81.                                                 }
  82.                                         }
  83.                                 }
  84.                         } catch (FileNotFoundException e) {
  85.                                 e.printStackTrace();
  86.                         } catch (IOException e) {
  87.                                 e.printStackTrace();
  88.                         } finally {
  89.                                 try {
  90.                                         System.out.println("length:"+length);
  91.                                         System.out.println("第"+(threadId+1)+"条线程下载完毕");
  92.                                         if (accessFile != null && in != null) {
  93.                                                 accessFile.close();
  94.                                                 in.close();
  95.                                         }
  96.                                 } catch (IOException e) {
  97.                                         e.printStackTrace();
  98.                                 }
  99.                         }
  100.                 }

  101.         }

  102. }
复制代码



评分

参与人数 1技术分 +1 收起 理由
ily521125 + 1

查看全部评分

1 个回复

倒序浏览
synchronized (object) {
  length+=len;
  System.out.println(length*100/accessFile.length()+"%");
}
加锁只加在变量这里就可以了,文件操作不用。

评分

参与人数 1技术分 +1 收起 理由
ily521125 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马