java多线程下载

Posted 风-fmgao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
        }
    }
}

 

以上是关于java多线程下载的主要内容,如果未能解决你的问题,请参考以下文章

java多线程断点下载原理(代码实例演示)

Java多线程断点下载文件并压缩

多线程下载

Java实现多线程下载

#私藏项目实操分享#Java多线程下载器基础代码

Java多线程文件下载性能