下载图片 复盘

168 阅读2分钟

学习老师的思想:

  1. 善于使用api ,有的功能java 类库已经实现了,我们就没必要再自己实现逻辑来完成了。
  2. TDD变成其实可以加快编写速度,IDE可以自动生成代码。

目标:

在规定时间内实现多线程下载一个图片

结果:

实现了,但延期了一天。

过程分析:

  1. 前期不动手,畏惧困难,在最后一天动手了,没承受住自己给自己的压力 ,没做完。
  2. 通过网络搜索了一个单线程下载的例子。知道了用 URL HttpURLConnection先获取连接,
  3. 在读取的时候比较受挫 ,FileInputStream 里的read(byte[] a)方法觉得api的解释跟结果怎么都不对,如果你是 a多大就读取几个的话,为什么要用循环读取,不能一次读完呢,其实是在网络信息的时候,一次读取的字节数并不能保证,所以要用while,读取本地文件不会出现这种情况
  4. 分三组读取的时候我用了标记和判断每个线程是不是已完成了isAlive()来判断线程是否完成, 有更好的方法就是栅栏 CyclicBarrier,类似锁住了,必须执行完所有的线程才能一起往后走

习得: 1: 时间上,现在开始 2:不要畏惧自己未知的技能和功能,大胆去思考,去实现

知识点:

  1. 和一个网络资源建立连接: URL uri= new URL(url地址); HttpURLConnection conn = uri.openConnection(); 设置网络资源读取位置:(相比读取到了再skip,效率更高) httpConn.setRequestProperty(“Range”, “bytes=” + startPos + “-” + endPos); 读取 InputStream is = httpConn.getInputStream();

  2. 读取到数据后,可以存入 缓存,以内存为操作对象的 FileInputStream 是以文件为操作对象的 ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(..) ; baos.toByteArray();

  3. 想要隐藏的类去掉修饰符,即受保护的,包内可见,外界可以只暴露一个获取的

  4. 栅栏 注意是await() 不是wait() ,这里使用错误过。

    CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_TRHEAD_NUM , new Runnable(){
      public void run(){
              listener.notifyFinished();
          }
      }); 

       public void run(){ 
         //......省略下载代码
  
         barrier.await(); //等待别的线程完成
  
  
      }
  1. RadomAccessFile 读写文件十分方便
        RandomAccessFile file = new RandomAccessFile(文件,"rw");
    
        file.seek(startPos);    
    
        file.write(data);
    
        file.close();

6.不一定文件有多大,就一定能读取到多少个字节,存在总大小>实际字节数的情况,因为不满一1KB 的会向上取整,例如37.5KB 大小是38KB,读取的时候要注意,不一定可以读取到整38KB的内容,不要数组越界