温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java多线程下载

发布时间:2020-07-22 01:00:24 来源:网络 阅读:474 作者:xiufang301 栏目:编程语言

ui界面:

package DownLoaderItem;
import javax.swing.*;
import java.awt.*;
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 DownLoaderUI extends JFrame implements ActionListener{

private JLabel lburl;
private TextField tfurl;
private DownLoader downLoader;
private JLabel lblocation;
private TextField tfloacation;
private JLabel lbcount;
private TextField tfcount;
private int completed=0;
private JButton btnstar;
public JButton btnpause;
public JProgressBar[] bars;

public DownLoaderUI(){
    init();
    this.setVisible(true);
}

private void init() {
    this.setBounds(100,50,800,600);
    this.setLayout(null);

    lburl=new JLabel("url地址");
    lburl.setBounds(0,0,100,30);
    this.add(lburl);

    tfurl=new TextField("http://localhost:8092/2018-07-01.log");
    tfurl.setBounds(0,40,800,30);
    this.add(tfurl);

    lblocation=new JLabel("保存地址");
    lblocation.setBounds(0,80,100,30);
    this.add(lblocation);

    tfloacation=new TextField("d:/test/down/2018-07-01.log");
    tfloacation.setBounds(0,120,800,30);
    this.add(tfloacation);

    lbcount=new JLabel("线程数");
    lbcount.setBounds(0,160,100,30);
    this.add(lbcount);

    tfcount=new TextField("3");
    tfcount.setBounds(0,200,800,30);
    this.add(tfcount);

    btnstar=new JButton("开始");
    btnstar.setBounds(0,240,100,30);
    btnstar.addActionListener(this);
    this.add(btnstar);

    btnpause=new JButton("暂停");
    btnpause.setBounds(150,240,100,30);
    btnpause.addActionListener(this);
    this.add(btnpause);

    this.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(-1);
        }
    });
}

@Override
public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    //如果点击事件为开始
    if(source==btnstar){
        String url = tfurl.getText();
        String location = tfloacation.getText();
        int count=Integer.parseInt(tfcount.getText());
        downLoader = new DownLoader(url, location, count, this);
        addBars(downLoader.getDownLoaderInfos());
        downLoader.startDownload();
        //如果点击事件为暂停
    }else if(source==btnpause){
        //通过调节下载线程中的静态标记,来调节按钮的名字与开始暂停
        DownLoaderThread.pause=!DownLoaderThread.pause;
        if(DownLoaderThread.pause){
            btnpause.setText("继续");
        }else{
            btnpause.setText("暂停");
        }
    }
}

private void addBars(List<DownLoaderInfo> list) {
    //添加进度条数组
    bars=new JProgressBar[list.size()];
    //循环所有的线程,创建进度条
    for (DownLoaderInfo di : list) {
        bars[di.getIndex()]=new JProgressBar();
        bars[di.getIndex()].setBounds(10,280+(di.getIndex()*50),750,30);
        //设置最大值
        bars[di.getIndex()].setMaximum(di.getEndPos()-di.getStartPose()+1);
        //取出上次进度条所走的进度值
        bars[di.getIndex()].setValue(di.getAmount());
        this.add(bars[di.getIndex()]);
    }
    this.repaint();
}

public void updataBars(int index, int len) {
    //更新进度条
    bars[index].setValue(bars[index].getValue()+len);
    synchronized (this){
        //如果一个进度条的值大于等于它的最大值了,就是下完了
        if(bars[index].getValue()>=bars[index].getMaximum()){
            completed++;
            //如果进度条的数量等于已下载的数量说明全下完了,就可以删除进度条了
            if(bars.length==completed){
                for (JProgressBar bar : bars) {
                    this.remove(bar);
                }
                this.repaint();
                completed=0;
                bars=null;
                downLoader.prop=null;
                //下完之后需要关闭进程
                BackWriteThread.stop=true;
                //下载完成后删除文件
                downLoader.deleteMetaFile();
            }
        }
    }
}
}

主入口:

package DownLoaderItem;

public class Mainx {
        public static void main(String[] args) {
                new DownLoaderUI();
        }
}

下载器类:

package DownLoaderItem;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DownLoader {
        private String url;
        private String location;
        private int count;
        //传递prop,把下载进度写入到prop中
        public Properties prop;
        //把下载信息组成集合
        public List<DownLoaderInfo> getDownLoaderInfos() {
                return downLoaderInfos;
        }
        public void setDownLoaderInfos(List<DownLoaderInfo> downLoaderInfos) {
                this.downLoaderInfos = downLoaderInfos;
        }
        private DownLoaderUI ui;
        public List<DownLoaderInfo> downLoaderInfos;

        public DownLoader(String url, String location, int count, DownLoaderUI ui) {
                this.url = url;
                this.location = location;
                this.count = count;
                this.ui = ui;
                initDownloaderInfos();
        }

        public void startDownload(){
                for (DownLoaderInfo di : downLoaderInfos) {
                        new DownLoaderThread(di,ui,this.prop).start();
                }
                //起新线程写入后台
                new BackWriteThread(location,prop).start();
        }

        private void initDownloaderInfos() {
                downLoaderInfos=new ArrayList<>();
                //如果是第一次下载
                if(!isFirst()){
                        int blockSize=getLen()/count;
                        for (int i=0;i<count;i++){
                                int startPos=i*blockSize;
                                int endPos=0;
                                if(i==count-1){
                                        endPos=getLen()-1;
                                }else {
                                        endPos=(i+1)*blockSize-1;
                                }
                                DownLoaderInfo d = new DownLoaderInfo(url, location, startPos, endPos, i, 0);
                                //把下载信息添加进集合
                                downLoaderInfos.add(d);
                        }
                        //首次下载后把元数据创建出来,并写入到文件
                        creatMetaDate(downLoaderInfos);
                        //如果不是首次下载
                }else {
                        try {
                                File f = new File(location + ".meta");
                                prop = new Properties();
                                FileInputStream fis = new FileInputStream(f);
                                prop.load(fis);
                                //取出线程数
                                int count = Integer.parseInt(prop.getProperty("thread.count"));
                                for (int i=0;i<count;i++){
                                        //循环所有线程,取出重要数据
                                        int startPos = Integer.parseInt(prop.getProperty("thread."+i+".startPos"));
                                        int endPos = Integer.parseInt(prop.getProperty("thread."+i+".endPos"));
                                        int amount = Integer.parseInt(prop.getProperty("thread."+i+".amount"));
                                        DownLoaderInfo d = new DownLoaderInfo(url, location, startPos, endPos, i, amount);
                                        downLoaderInfos.add(d);
                                }
                        }catch (Exception e){
                                e.printStackTrace();
                        }
                }
        }

        private void creatMetaDate(List<DownLoaderInfo> list) {
                try {
                        File f = new File(location + ".meta");
                        prop = new Properties();
                        prop.setProperty("thread.count",list.size()+"");
                        //循环线程,把重要数据写入到元数据文件
                        for (DownLoaderInfo di : list) {
                                prop.setProperty("thread."+di.getIndex()+".startPos",di.getStartPose()+"");
                                prop.setProperty("thread."+di.getIndex()+".endPos",di.getEndPos()+"");
                                prop.setProperty("thread."+di.getIndex()+".amount",di.getAmount()+"");
                        }
                        FileOutputStream fos = new FileOutputStream(f);
                        prop.store(fos,"xxx");
                        fos.close();
                }catch (Exception e){
                        e.printStackTrace();
                }
        }

        public boolean isFirst(){
                return new File(location).exists();
        }

        //获得url,与下载文件的长度
        public int getLen(){
                try {
                        URL u = new URL(this.url);
                        HttpURLConnection conn= (HttpURLConnection) u.openConnection();
                        int len = conn.getContentLength();
                        conn.disconnect();
                        return len;
                }catch (Exception e){
                        e.printStackTrace();
                }
                return -1;
        }

        //删除元数据文件
        public void deleteMetaFile(){
                File f = new File(location + ".meta");
                while (!f.delete()){

                }

        }
}

下载线程类:

package DownLoaderItem;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;

public class DownLoaderThread extends Thread {
        private DownLoaderInfo info;
        private DownLoaderUI ui;
        public static boolean pause=false;
        private Properties prop;

        public DownLoaderThread(DownLoaderInfo info, DownLoaderUI ui,Properties prop) {
                this.info = info;
                this.ui = ui;
                this.prop=prop;
        }

        @Override
        public void run() {
                try {
                        URL u = new URL(info.getUrl());
                        HttpURLConnection conn= (HttpURLConnection) u.openConnection();
                        //设置下载偏移量
                        conn.setRequestProperty("Range","bytes="+(info.getStartPose()+info.getAmount())+"-"+info.getEndPos());
                        InputStream in = conn.getInputStream();
                        RandomAccessFile raf = new RandomAccessFile(info.getLocation(), "rw");
                        //取得下载偏移量
                        raf.seek(info.getStartPose()+info.getEndPos());
                        byte[] buf=new byte[1024];
                        int len=0;
                        while((len=in.read(buf))!=-1){
                                //如果标记为为true就暂停
                                while(pause){
                                        Thread.sleep(1000);
                                }
                                raf.write(buf,0,len);
                                //更新下载进度到prop线程
                                updataAmount(info.getIndex(),len);
                                //更新进度条
                                ui.updataBars(info.getIndex(),len);
                                Thread.sleep(1);
                        }
                        raf.close();
                        in.close();
                        conn.disconnect();
                }catch (Exception e){
                        e.printStackTrace();
                }
        }

        //更新amount到prop
        private void updataAmount(int index, int len) {
                int amount = Integer.parseInt(prop.getProperty("thread."+index+".amount"));
                prop.setProperty("thread."+index+".amount",(amount+len)+"");

        }
}

封装下载信息类:

package DownLoaderItem;
public class DownLoaderInfo {
        private String url;
        private String location;
        private int startPose;
        private int endPos;
        private int index;

        public DownLoaderInfo(String url, String location, int startPose, int endPos,int index) {
                this.url = url;
                this.location = location;
                this.startPose = startPose;
                this.endPos = endPos;
                this.index=index;
        }

        public int getIndex() {
                return index;
        }

        public void setIndex(int index) {
                this.index = index;
        }

        public String getUrl() {
                return url;
        }

        public void setUrl(String url) {
                this.url = url;
        }

        public String getLocation() {
                return location;
        }

        public void setLocation(String location) {
                this.location = location;
        }

        public int getStartPose() {
                return startPose;
        }

        public void setStartPose(int startPose) {
                this.startPose = startPose;
        }

        public int getEndPos() {
                return endPos;
        }

        public void setEndPos(int endPos) {
                this.endPos = endPos;
        }
}

后台分线程写入文件类:

package DownLoaderItem;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;

public class BackWriteThread extends Thread {
        private String location;
        private Properties prop;
        public static boolean stop=false;

        public BackWriteThread(String location, Properties prop) {
                this.location = location;
                this.prop = prop;
                this.setDaemon(true);
        }

        @Override
        public void run() {
                //把最新的进度通过分线程写到文件中
                File f = new File(location + ".meta");
                try {
                        while(f.exists() && prop!=null) {
                                if(stop){
                                        return;
                                }
                                FileOutputStream fos = new FileOutputStream(f);
                                prop.store(fos, "xxx");
                                fos.close();
                                Thread.sleep(1000);
                        }
                }catch (Exception e){
                        e.printStackTrace();
                }
        }
}
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI