zoukankan      html  css  js  c++  java
  • 应用多线程解决文件拷贝加进度条项目

    大家好!!!            这周给你们分享关于文件拷贝和附加进度条(百分比)的制作,博主也是才接触多线程 所以如果有看到这篇博客的大牛 还望提提建议 分享分享关于多线程的经验

    废话不多说 直接上代码!!!(这里有2种做法 我自己的和我老师的,大家可以都看看 选择容易接受的 虽然我感觉我做的比我们老师的做法复杂很多)

    这是我的做法:

    public class Exp2 extends Thread{
    /**
    * 总字节数
    */
    static double bytes;
    static double bytex;
    /**
    * 当前字节数
    */
    static double newbytes;

    @Override
    public void run() {
    while(true){
    String progress = NumberFormat.getPercentInstance().format(1-(newbytes/bytex));

    System.out.println(progress);

    try {
    sleep(1);
    } catch (InterruptedException e) {

    e.printStackTrace();
    }
    }
    }
    /**
    * 主方法实现拷贝
    * @param args
    * @throws IOException
    * @throws InterruptedException
    */
    public static void main(String[] args) throws IOException, InterruptedException {
    File source = new File("E:\音乐\周杰伦-半岛铁盒(超清).mp4");
    File targetDir = new File("E:\Temp");
    File file = new File(targetDir,source.getName());
    InputStream is = new FileInputStream(source);
    OutputStream os = new FileOutputStream(file);

    int len = 0;
    byte[] b = new byte[1024];
    bytes = source.length();
    bytex = bytes;

    Exp2 ex = new Exp2();
    ex.setDaemon(true);
    ex.start();
    while((len = is.read(b)) != -1){

    os.write(b,0,len);

    newbytes = bytes - b.length;

    bytes = newbytes;
    }

    os.close();
    is.close();
    System.out.println("复制成功");
    }

    开始分析代码

    我们先整理一下思路  如果是只用拷贝文件那么就很简单了 但是怎么加进度条呢? 

    就是说 , 怎么把进度条的进度与文件拷贝的进度联系起来 这应该算一个难点  你们有什么办法吗?

    答案是把拷贝文件当前的字节数传给另一个进度条线程  有了基本思路我们就好实现功能了.我的做法是把拷贝当做一个主线程(main方法本身就是个线程) 然后在创建一个进度条线程 不停地统计当前(1-字节数和总字节数之比)   注意:当前字节数和总字节数一定要定义成double类型变量 因为如果是整型的话 得到的进度会一直是0   而且建议大家在使用多线程的时候尽量不要用static修饰变量 因为多个线程访问同一数据会导致并发数据异常  但是这个项目就无所谓了 因为main方法根本就没用到我们定义的static变量 所以不会引起数据异常  这里必须定义一个临时变量  用以时刻更新新的字节数  

    还有就是一定要在设置守护线程(在主线程结束后 守护线程也会跟着结束)之后 再启动线程    


    下面是我们柴老师的做法:

    public class FileCopyByThread extends Thread{
    private File source;
    private File target;
    //总大小
    private double totalSize;
    //当前大小
    private double currentSize;


    public FileCopyByThread(File source, File target) {
    super();
    this.source = source;
    this.target = target;
    }


    @Override
    public void run() {
    try(
    FileInputStream fis = new FileInputStream(source);
    FileOutputStream fos = new FileOutputStream(target);
    ){
    //获取文件的实际大小
    totalSize = source.length();
    byte[] b = new byte[1024];
    int len = 0;
    //read() 读取一个字节 返回字节内容
    //read(byte[] b) 将读取的数据装入字节数组 返回真实的读取长度
    System.out.println(getName() + "开始拷贝:" + source.getName());
    ProgressListener pl = new ProgressListener();
    //设置当前线程为守护线层
    pl.setDaemon(true);
    pl.start();
    while((len = fis.read(b))!= -1){
    fos.write(b, 0, len);
    currentSize += len;
    }
    System.out.println("拷贝完成");
    }catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * 计算文件拷贝线程
    * @author 雷神
    *
    */
    class ProgressListener extends Thread {

    @Override
    public void run() {
    while(true) {
    //计算进度
    double d =currentSize / totalSize;
    //将浮点的进度格式化为百分比
    String progress = NumberFormat.getPercentInstance().format(d);
    System.out.println("拷贝进度:" + progress);
    try {
    sleep(20);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }

    public static void main(String[] args) {



    File source = new File("E:\音乐\周杰伦-半岛铁盒(超清).mp4");

    File target = new File("E:\Temp\周杰伦-半岛铁盒(超清).mp4");

    new FileCopyByThread(source, target).start();
    }
    }

    柴哥这里定义了一个内部类 当时我没想到内部类,定义内部类的话这样数据就共享了,还有就是柴哥是直接用一个全局变量计算当前的字节数(我当时是真不知道还有 +=len来统计当前字节数的操作,之前对len这个变量一直处于半知半解的状态),最后将得到的double值用NumberFormat格式化成百分数

    柴哥这个相当于是我的优化版  但是初学者看到我的代码应该更容易理解一点哈哈哈 最后附上代码运行结果:

     大家学到东西了吗? 其实这类问题的难点是想出怎么做 而不是难在具体的实现过程  有时候思维真的比代码熟练度要重要 所以大家有时间一定要多做点算法题 开阔思维!!!

  • 相关阅读:
    【GoLang】GoLang map 非线程安全 & 并发度写优化
    【IDEA】IDEA 如何设置编辑器字体大小
    【GoLang】GoLang fmt 占位符详解
    转头条:阿里p7架构师:三年经验应该具备什么样的技能?
    RPC与RMI的区别
    为什么使用消息队列,为什么使用RabbitMQ、springAMQP
    cookie的安全性问题
    solr与mysql数据同步的方案
    springcloud与dubbo对比:
    mybatis与分布式事务的面试
  • 原文地址:https://www.cnblogs.com/j-1-z-2-s-3/p/13337240.html
Copyright © 2011-2022 走看看