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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

5黑马币
我用了四条输入线程,加四条输出线程,来拷贝源文件,
结果还是慢了电脑自带的慢一大截。
希望大神能给个超电脑的。。
下面是我用多线程重新做的大文件拷贝程序:
  1. import java.io.IOException;

  2. /*
  3. * 将一个电影文件,拷贝到其他盘。模拟下载,要求使用多线程
  4. * 分析:
  5. * 1,通过File对象关联源文件,并获取其大小。
  6. * 2,通过File对象创建一个和源文件大小相同的(空)文件
  7. * 3,通过随机流RandomAccessFile读取源文件,
  8. * 4,将读取的数据写入到输出管道流PipedOutputStream,
  9. * 5,管道读取流PipedInputStream读取输出流中的数据,并通过随机流写入到目的文件中。
  10. *

  11. */



  12. public class TestTwo {

  13.         public static void main(String[] args) throws IOException {
  14. Copy.copy("C:\\Mon.mp4","C:\\Moncy.mp4");
  15.         }

  16. }
复制代码
Copy进行拷贝操作:
  1. import java.io.File;
  2. import java.io.IOException;
  3. import java.io.PipedInputStream;
  4. import java.io.PipedOutputStream;
  5. import java.io.RandomAccessFile;

  6. public class Copy {

  7.         public static void main(String[] args) {

  8.         }

  9.         public static boolean copy(String source, String destination) throws IOException  {
  10.                 File socefile = new File(source);
  11.                 File destfile = new File(destination);
  12.                 if(socefile.isHidden())
  13.                         throw new RuntimeException("源文件不可操作");
  14.                
  15.                 //目的文件初始化,使其和源文件大小一致。
  16.                 RandomAccessFile soceRaf = new RandomAccessFile(socefile,"r");
  17.                 RandomAccessFile destRaf = new RandomAccessFile(destfile,"rwd");
  18.                 destRaf.setLength(soceRaf.length());
  19.                 long index = soceRaf.getFilePointer();
  20.                 soceRaf.close();
  21.                 destRaf.close();
  22.                
  23.                 //把源文件切成4段,每段的最小的(最接近负无穷大)double 值,该值大于等于参数,
  24.                 //保证数据不丢失。最后一段单独处理,因为数据可能会小于len。
  25.                 long len = (long) Math.ceil(socefile.length()/4);
  26.                 for(int x=0 ; x<4 ; x++){
  27.                         PipedOutputStream pos = new PipedOutputStream();
  28.                         PipedInputStream pis = new PipedInputStream(pos);
  29.                         //为了使每个线程都有一个自己独立的指针,为每个对象建立独自的随机流
  30.                         new Thread(new PipedOut
  31.                                 (pos,new RandomAccessFile(socefile,"r"),index,len)).start();;
  32.                         new Thread(new PipedIn
  33.                                 (pis,new RandomAccessFile(destfile,"rwd"),index,len)).start();
  34.                         index = index + len ;
  35.                 }
  36.                
  37.                 return true;
  38.                
  39.                 /*无限代码,用于测试的
  40.                  * PipedOutputStream pos = new PipedOutputStream();
  41.                 PipedInputStream pis = new PipedInputStream(pos);
  42.                 long len = soceRaf.length();
  43.                 new Thread(new PipedOut(pos,soceRaf,index,len)).start();
  44.                 new Thread(new PipedIn(pis,destRaf,index,len)).start();
  45.                 */
  46.                
  47.                
  48.                
  49.                
  50.         }

  51. }
复制代码
PipedOut :通过随机流读取,并写入到管道流中:
  1. import java.io.BufferedOutputStream;
  2. import java.io.IOException;
  3. import java.io.PipedOutputStream;
  4. import java.io.RandomAccessFile;

  5. public class PipedOut implements Runnable{
  6.         BufferedOutputStream pos;
  7.         RandomAccessFile soceRaf;
  8.         long index;
  9.         long len;
  10.         PipedOut(PipedOutputStream pos, RandomAccessFile soceRaf, long index, long len) {
  11.                 super();
  12.                 this.pos = new BufferedOutputStream(pos);
  13.                 this.soceRaf = soceRaf;
  14.                 this.index = index;
  15.                 this.len = len;
  16.         }
  17.         public void run() {
  18.                
  19.                 try {
  20.                         byte[] buf = new byte[1024*1024*20];
  21.                         int length = 0 ;
  22.                         soceRaf.seek(index);//设置指针位置
  23.                         //如果没有循环超出数据位置,或者在到结尾。
  24.                         while(soceRaf.getFilePointer()<index+len){
  25.                                 if((length=soceRaf.read(buf))!=-1){
  26.                                         pos.write(buf,0,length);
  27.                                         pos.flush();
  28.                                 }
  29.                                 else
  30.                                         break;
  31.                         }
  32.                 //如果是因为循环超出数据位置导致的结束,则计算出有效的数组长度
  33.                         if(length==buf.length){
  34.                                  length =(int) ((long)length - ( soceRaf.getFilePointer()-(index+len) ));
  35.                                  System.out.println(length);
  36.                                 pos.write(buf,0,length);
  37.                         }
  38.                         pos.close();
  39.                         soceRaf.close();
  40.                 }
  41.                 catch (IOException e) {
  42.                         e.printStackTrace();
  43.                 }
  44.                
  45.                

  46.                 /*
  47.                  * 无效代码用于测试的
  48.                 try {
  49.                         byte[] buf = new byte[1024*100];
  50.                         int length = 0 ;
  51.                         soceRaf.seek(index);//设置指针位置
  52.                         //如果没有循环超出数据位置,或者在到结尾。
  53.                         while((length=soceRaf.read(buf))!=-1){
  54.                                 pos.write(buf,0,length);
  55.                                 pos.flush();
  56.                         }
  57.                         pos.close();
  58.                         soceRaf.close();
  59.                 }
  60.                 catch (IOException e) {
  61.                         e.printStackTrace();
  62.                 }
  63.                 */
  64.                
  65.         }
  66.        

  67. }
复制代码
PipedIn 从管道流中读取数据,并通过任意流写入到目的文件中:
  1. import java.io.BufferedInputStream;
  2. import java.io.IOException;
  3. import java.io.PipedInputStream;
  4. import java.io.RandomAccessFile;

  5. public class PipedIn implements Runnable {

  6.         BufferedInputStream pis;
  7.         RandomAccessFile destRaf;
  8.         long index;
  9.         long len;
  10.        
  11.         PipedIn(PipedInputStream pis, RandomAccessFile destRaf, long index, long len) {
  12.                 super();
  13.                 this.pis =new BufferedInputStream(pis);
  14.                 this.destRaf = destRaf;
  15.                 this.index = index;
  16.                 this.len = len;
  17.         }

  18.         public void run() {
  19.                
  20.                 try {
  21.                         byte[] buf = new byte[1024*1024*20];
  22.                         int length = 0 ;
  23.                         destRaf.seek(index);//设置指针位置
  24.                        
  25.                         //读取管道流中的数据,并写入目的文件中
  26.                         while((length=pis.read(buf))!=-1){
  27.                                 destRaf.write(buf,0,length);
  28.                         }
  29.                         pis.close();
  30.                         destRaf.close();
  31.                         System.out.println("over");
  32.                 } catch (IOException e) {
  33.                         e.printStackTrace();
  34.                 }
  35.         }

  36. }
复制代码
比起单线程切实是快乐好多倍,但是和电脑自带的比起来,简直就是满满的挫败感。。。
感觉自己当初的懵懂的大志疑惑幻想,是怎么的可笑,如果还有比windows更快更好的,windows一定早就用了吧?
换句话说,windows现在用的岂能不是最好最优的,,,
呵,我也只能带着自己无知无畏最后的无奈匆匆一笑,希望在今后遇到问题能去进一步想想,少一些不切实际幻想,
有想法是好的,关键跟要有这样的实力,敢于幻想,更要能加以辩论!




3 个回复

倒序浏览
题外话:我拷贝大文件的时候习惯用fastcopy 可以自定义复制的内存 确实要比windows自带的快得多 windows自带的给的内存才128M
回复 使用道具 举报
Weidan 发表于 2015-11-29 22:21
题外话:我拷贝大文件的时候习惯用fastcopy 可以自定义复制的内存 确实要比windows自带的快得多 windows自带 ...

谢谢!但是我用的是固态硬盘,不差这点时间
介绍给室友了
回复 使用道具 举报
参考下别人的高级算法吧。我们的是最基本的算法而已
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马