java多线程下载
一个进度条
App
package com.sly.uploadfile.base.mulcopier; /** * Created by admin on 2020/6/27. */ public class App { public static void main(String[] args) { CopyUI ui = new CopyUI(); } }
Copier
package com.sly.uploadfile.base.mulcopier; import java.io.RandomAccessFile; /** * 复制器 */ public class Copier { private CopyUI copyUI; //源文件 private String srcFile; //目标目录 private String destDir; // 线程数 private int count; public Copier(CopyUI copyUI, String srcFile, String destDir, int count) { this.copyUI = copyUI; this.srcFile = srcFile; this.destDir = destDir; this.count = count; } /** * 开始赋值文件 */ public void startCopy() { try { int start = 0; int end = 0; // 计算文件大小 RandomAccessFile raf = new RandomAccessFile(srcFile, "r"); int fileLength = (int) raf.length(); // 设置进度条的最大值 copyUI.bar.setMaximum(fileLength); // 每个线程赋值的快大小 int block = fileLength / count; for (int i = 0; i < count; i++) { start = i * block; if (i != (count - 1)) { end = (i + 1) * block - 1; } else { end = fileLength - 1; } new CopyThread(copyUI, srcFile, destDir, start, end).start(); } } catch (Exception e) { e.printStackTrace(); } } }
CopyThread
package com.sly.uploadfile.base.mulcopier; import java.io.RandomAccessFile; /** * 复制线程 */ public class CopyThread extends Thread { private CopyUI copyUI; //源文件 private String srcFile; //目标目录 private String destDir; private int start; private int end; public CopyThread(CopyUI copyUI, String srcFile, String destDir, int start, int end) { this.copyUI = copyUI; this.srcFile = srcFile; this.destDir = destDir; this.start = start; this.end = end; } public void run() { try { // 定位源文件 RandomAccessFile src = new RandomAccessFile(srcFile, "r"); src.seek(start); // 定位目标文件 RandomAccessFile dest = new RandomAccessFile(destDir, "rw"); dest.seek(start); byte[] buffer = new byte[1024]; // 计算复制两 int amount = end - start + 1; int loopNum = 0; // 剩余数 int remain = amount % buffer.length; if (remain == 0) { loopNum = amount / buffer.length; } else { loopNum = amount / buffer.length + 1; } for (int i = 0; i < loopNum; i++) { // 不是最后一次 if (i != (loopNum - 1)) { src.read(buffer); dest.write(buffer); synchronized (CopyThread.class) { copyUI.bar.setValue(copyUI.bar.getValue() + buffer.length); } } else { byte[] buffer0 = null; if (remain == 0) { buffer0 = buffer; } else { buffer0 = new byte[remain]; } src.read(buffer0); dest.write(buffer0); synchronized (CopyThread.class) { copyUI.bar.setValue(copyUI.bar.getValue() + buffer0.length); } } } src.close(); dest.close(); } catch (Exception e) { e.printStackTrace(); } } }
CopyUI
package com.sly.uploadfile.base.mulcopier; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; /** * 主窗口 */ public class CopyUI extends JFrame implements ActionListener { private static final long serialVersionUID = -2484619506316087721L; // 源文件 private JLabel lblSrcFile; private JTextField tfSrcFile; // 目标文件 private JLabel lblDestDir; private JTextField tfDestDir; private JLabel lblCount; private JTextField tfCount; private JButton btnStart; public JProgressBar bar; public CopyUI() { init(); } private void init() { this.setTitle("主窗口"); this.setBounds(100, 100, 800, 600); this.setLayout(null); // SrcFile标签 lblSrcFile = new JLabel("源文件"); lblSrcFile.setBounds(10, 10, 80, 30); this.add(lblSrcFile); tfSrcFile = new JTextField(); tfSrcFile.setBounds(60, 10, 400, 30); tfSrcFile.setText("D:\\soft\\JetBrains.zip"); this.add(tfSrcFile); // destDir标签 lblDestDir = new JLabel("目标文件"); lblDestDir.setBounds(10, 80, 80, 30); this.add(lblDestDir); tfDestDir = new JTextField(); tfDestDir.setBounds(60, 80, 400, 30); tfDestDir.setText("D:/JetBrains.zip"); this.add(tfDestDir); // 线程数 lblCount = new JLabel("线程数"); lblCount.setBounds(10, 110, 80, 30); this.add(lblCount); tfCount = new JTextField(); tfCount.setBounds(60, 110, 600, 30); tfCount.setText("" + 5); this.add(tfCount); // 开始按钮 btnStart = new JButton("开始"); btnStart.setBounds(10, 160, 100, 30); this.add(btnStart); btnStart.addActionListener(this); // 进度条 bar = new JProgressBar(); bar.setBounds(10, 200, 700, 50); this.add(bar); this.setVisible(true); //设置窗口适配器 this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(-1); } }); } // 添加按钮监听 public void actionPerformed(ActionEvent e) { Object es = e.getSource(); //开始按钮 if (es == btnStart) { String srcFile = tfSrcFile.getText(); String destDir = tfDestDir.getText(); int count = Integer.parseInt(tfCount.getText()); // 创建复制器对象 Copier copier = new Copier(this, srcFile, destDir, count); copier.startCopy(); } } }
多进度条
App
package com.sly.uploadfile.base.mulcopier2; public class App { public static void main(String[] args) { CopyUI ui = new CopyUI(); } }
Copier
package com.sly.uploadfile.base.mulcopier2; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; /** * 复制器 */ public class Copier { private CopyUI copyUI; //源文件 private String srcFile; //目标目录 private String destDir; // 线程数 private int count; // 每个线程复制信息的集合 public List<CopyInfo> infos; public Copier(CopyUI copyUI, String srcFile, String destDir, int count) { this.copyUI = copyUI; this.srcFile = srcFile; this.destDir = destDir; this.count = count; initCopyInfos(); } /** * 初始化赋值信息的集合 */ private void initCopyInfos() { try { infos = new ArrayList<>(); // 计算文件大小 RandomAccessFile raf = new RandomAccessFile(srcFile, "r"); int fileLength = (int) raf.length(); // 每个线程赋值的快大小 int block = fileLength / count; int start = 0; int end = 0; for (int i = 0; i < count; i++) { start = i * block; if (i != (count - 1)) { end = (i + 1) * block - 1; } else { end = fileLength - 1; } CopyInfo info = new CopyInfo(); info.setIndex(i); info.setSrcFile(srcFile); info.setDestDir(destDir); info.setStart(start); info.setEnd(end); infos.add(info); } } catch (Exception e) { e.printStackTrace(); } } /** * 开始复制文件 */ public void startCopy() { for (CopyInfo info : infos) { new CopyThread(copyUI, info).start(); } } }
CopyInfo
package com.sly.uploadfile.base.mulcopier2; public class CopyInfo { private int index; //源文件 private String srcFile; //目标目录 private String destDir; private int start; private int end; public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public String getSrcFile() { return srcFile; } public void setSrcFile(String srcFile) { this.srcFile = srcFile; } public String getDestDir() { return destDir; } public void setDestDir(String destDir) { this.destDir = destDir; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public int getEnd() { return end; } public void setEnd(int end) { this.end = end; } }
CopyThread
package com.sly.uploadfile.base.mulcopier2; import java.io.RandomAccessFile; /** * 复制线程 */ public class CopyThread extends Thread { private CopyUI copyUI; private CopyInfo info; public CopyThread(CopyUI copyUI, CopyInfo info) { this.copyUI = copyUI; this.info = info; } public void run() { try { // 定位源文件 RandomAccessFile src = new RandomAccessFile(info.getSrcFile(), "r"); src.seek(info.getStart()); // 定位目标文件 RandomAccessFile dest = new RandomAccessFile(info.getDestDir(), "rw"); dest.seek(info.getStart()); byte[] buffer = new byte[1024]; // 计算复制两 int amount = info.getEnd() - info.getStart() + 1; int loopNum = 0; // 剩余数 int remain = amount % buffer.length; if (remain == 0) { loopNum = amount / buffer.length; } else { loopNum = amount / buffer.length + 1; } for (int i = 0; i < loopNum; i++) { // 不是最后一次 if (i != (loopNum - 1)) { src.read(buffer); dest.write(buffer); copyUI.updateBar(info.getIndex(), buffer.length); } else { byte[] buffer0 = null; if (remain == 0) { buffer0 = buffer; } else { buffer0 = new byte[remain]; } src.read(buffer0); dest.write(buffer0); copyUI.updateBar(info.getIndex(), buffer0.length); } } src.close(); dest.close(); } catch (Exception e) { e.printStackTrace(); } } }
CopyUI
package com.sly.uploadfile.base.mulcopier2; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List; /** * 主窗口 */ public class CopyUI extends JFrame implements ActionListener { private static final long serialVersionUID = -2484619506316087721L; // 源文件 private JLabel lblSrcFile; private JTextField tfSrcFile; // 目标文件 private JLabel lblDestDir; private JTextField tfDestDir; private JLabel lblCount; private JTextField tfCount; private JButton btnStart; private JProgressBar[] bars; public CopyUI() { init(); } private void init() { this.setTitle("主窗口"); this.setBounds(100, 100, 800, 600); this.setLayout(null); // SrcFile标签 lblSrcFile = new JLabel("源文件"); lblSrcFile.setBounds(10, 10, 80, 30); this.add(lblSrcFile); tfSrcFile = new JTextField(); tfSrcFile.setBounds(60, 10, 400, 30); tfSrcFile.setText("D:\\soft\\JetBrains.zip"); this.add(tfSrcFile); // destDir标签 lblDestDir = new JLabel("目标文件"); lblDestDir.setBounds(10, 80, 80, 30); this.add(lblDestDir); tfDestDir = new JTextField(); tfDestDir.setBounds(60, 80, 400, 30); tfDestDir.setText("D:/a.zip"); this.add(tfDestDir); // 线程数 lblCount = new JLabel("线程数"); lblCount.setBounds(10, 110, 80, 30); this.add(lblCount); tfCount = new JTextField(); tfCount.setBounds(60, 110, 600, 30); tfCount.setText("" + 5); this.add(tfCount); // 开始按钮 btnStart = new JButton("开始"); btnStart.setBounds(10, 160, 100, 30); this.add(btnStart); btnStart.addActionListener(this); this.setVisible(true); //设置窗口适配器 this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(-1); } }); } // 添加按钮监听 public void actionPerformed(ActionEvent e) { Object es = e.getSource(); //开始按钮 if (es == btnStart) { String srcFile = tfSrcFile.getText(); String destDir = tfDestDir.getText(); int count = Integer.parseInt(tfCount.getText()); // 创建复制器对象 Copier copier = new Copier(this, srcFile, destDir, count); // 动态添加进度条 addBars(copier.infos); //开始复制 copier.startCopy(); } } /** * 动态添加进度条 */ private void addBars(List<CopyInfo> infos) { bars = new JProgressBar[infos.size()]; for (CopyInfo info : infos) { bars[info.getIndex()] = new JProgressBar(); bars[info.getIndex()].setBounds(10, 200 + info.getIndex() * 53, 650, 50); bars[info.getIndex()].setMaximum(info.getEnd() - info.getStart() + 1); this.add(bars[info.getIndex()]); } this.repaint(); } /** * 更新进度条 */ private int completeCount = 0; public void updateBar(int index, int length) { bars[index].setValue(bars[index].getValue() + length); // if (bars[index].getValue() >= bars[index].getMaximum()) { completeCount++; processFinish(); } } private synchronized void processFinish() { if (completeCount >= bars.length) { // 删除进度条 for (JProgressBar bar : bars) { this.remove(bar); } this.repaint(); } } }