应用多线程解决文件拷贝加进度条项目

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

废话不多说 直接上代码!!!(这里有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格式化成百分数

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

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

原文地址:https://www.cnblogs.com/j-1-z-2-s-3/p/13337240.html