多线程下载

Posted 艺海浮台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程下载相关的知识,希望对你有一定的参考价值。

public class DownloadUI extends JFrame {
    public static void main(String[] args) {
        new DownloadUI();
    }

    private JLabel lblUrl;
    private JLabel lblLocalPath;
    private JLabel lblCount;
    private JTextField tfUrl;
    private JTextField tfLocalPath;
    private JTextField tfCount;
    private JProgressBar[] bars;

    public DownloadUI() throws HeadlessException {
        init();
        this.setVisible(true);
    }

    public void init() {
        this.setTitle("下载器");
        this.setLayout(null);
        this.setBounds(300, 100, 700, 600);

        lblUrl = new JLabel("下载地址");
        lblUrl.setBounds(0, 0, 500, 50);
        this.add(lblUrl);

        tfUrl = new JTextField();
        tfUrl.setBounds(0, 50, 600, 50);
        tfUrl.setText("http://localhost:8080/abd.mp3");
        this.add(tfUrl);

        lblLocalPath = new JLabel("保存地址");
        lblLocalPath.setBounds(0, 100, 500, 50);
        this.add(lblLocalPath);

        tfLocalPath = new JTextField();
        tfLocalPath.setBounds(0, 150, 600, 50);
        tfLocalPath.setText("d:/ziling.mp3");
        this.add(tfLocalPath);

        lblCount = new JLabel("线程数地址");
        lblCount.setBounds(0, 200, 500, 50);
        this.add(lblCount);

        tfCount = new JTextField();
        tfCount.setBounds(0, 250, 600, 50);
        tfCount.setText("3");
        this.add(tfCount);
        // 开始下载
        JButton btnStart = new JButton();
        btnStart.setBounds(100, 450, 150, 50);
        btnStart.setText("start");
        btnStart.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String url = tfUrl.getText();
                String localPath = tfLocalPath.getText();
                int count = Integer.parseInt(tfCount.getText());
                // 创建下载器
                Downloader downloader = new Downloader(url, localPath, count, DownloadUI.this);
                // 动态添加进度条
                addBars(downloader.getInfos());
                downloader.start();
            }
        });
        this.add(btnStart);
        JButton btnPause = new JButton();
        btnPause.setBounds(300, 450, 150, 50);
        btnPause.setText("pause");
        btnPause.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                DownloadThread.pausing = !DownloadThread.pausing;
            }
        });
        this.add(btnPause);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(-1);
            }
        });
    }
    private void addBars(List<DownloadInfo> infos) {
        int yoffset = 330;
        bars = new JProgressBar[infos.size()];
        for (int i = 0; i < infos.size(); i++) {
            DownloadInfo info = infos.get(i);
            JProgressBar bar = new JProgressBar();
            bar.setBounds(0, yoffset + 20 * i, 600, 10);
            bar.setMaximum(info.getEndPos() - info.getStartPos() + 1);
            bars[info.getIndex()] = bar;
            this.add(bar);
            this.repaint();
        }
    };

    public void updateBar(int index, int len) {
        bars[index].setValue(bars[index].getValue() + len);
    }
}


//下载过程的管理器
public class Downloader {
    private String url;
    private String localPath;
    private int count;
    private int fileLength;
    private DownloadUI ui;
    //下载信息的集合
    private List<DownloadInfo> infos=new ArrayList<>();
    public Downloader(String url, String localPath, int count, DownloadUI ui) {
        super();
        this.url = url;
        this.localPath = localPath;
        this.count = count;
        this.ui = ui;
        initDownload();
    }
    
    public int getFileLength() {
        return fileLength;
    }

    public void setFileLength(int fileLength) {
        this.fileLength = fileLength;
    }

    public List<DownloadInfo> getInfos() {
        return infos;
    }

    public void setInfos(List<DownloadInfo> infos) {
        this.infos = infos;
    }
//初始化下载
    private void initDownload() {
        try {
            URL u = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) u.openConnection();
            this.fileLength = conn.getContentLength();
            conn.disconnect();
            //计算下载信息集合
            //每块下载的大小
            int blockSize=fileLength/count;
            int startPos=0;
            int endPos=0;
            for(int i=0;i<count;i++){
                DownloadInfo info=new DownloadInfo();
                info.setUrl(url);
                info.setLocalPath(localPath);
                info.setIndex(i);
                startPos=i*blockSize;
                info.setStartPos(startPos);
                if(i !=(count-1)){
                    endPos=(i+1)*blockSize-1;
                }
                else{
                    endPos=fileLength-1;
                }
                info.setEndPos(endPos);
                infos.add(info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //开始下载
    public void start(){
        for (DownloadInfo info : infos) {
            new DownloadThread(ui,info).start();
        }
    }
}


public class DownloadThread extends Thread{
    private DownloadUI ui;
    private DownloadInfo info;
    public static boolean pausing=false;
    public DownloadThread(DownloadUI ui, DownloadInfo info) {
        this.ui=ui;
        this.info=info;
    }

    public void run() {
        try {
            RandomAccessFile raf = new RandomAccessFile(info.getLocalPath(), "rw");
            raf.seek(info.getStartPos());
            URL url = new URL(info.getUrl());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("Range", "bytes="+info.getStartPos()+"-"+info.getEndPos());
            conn.setRequestMethod("GET");
            InputStream is = conn.getInputStream();
            byte[] buf=new byte[1024];
            int len=-1;
            while((len=is.read(buf))!=-1){
                while(pausing){
                    Thread.sleep(1000);
                }
                raf.write(buf,0,len);
                Thread.sleep(5);
                ui.updateBar(info.getIndex(),len);
            }
            is.close();
            raf.close();
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}



public class DownloadInfo {
    private String url;
    private String localPath;
    private int index;
    private int startPos;
    private int endPos;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getLocalPath() {
        return localPath;
    }
    public void setLocalPath(String localPath) {
        this.localPath = localPath;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    public int getStartPos() {
        return startPos;
    }
    public void setStartPos(int startPos) {
        this.startPos = startPos;
    }
    public int getEndPos() {
        return endPos;
    }
    public void setEndPos(int endPos) {
        this.endPos = endPos;
    }
    
}

 

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

多线程下载

多线程 Thread 线程同步 synchronized

多个用户访问同一段代码

线程学习知识点总结

多个请求是多线程吗

python小白学习记录 多线程爬取ts片段