溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java多線程下載

發(fā)布時間:2020-07-22 01:00:24 來源:網絡 閱讀:486 作者: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("線程數(shù)");
    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){
        //通過調節(jié)下載線程中的靜態(tài)標記,來調節(jié)按鈕的名字與開始暫停
        DownLoaderThread.pause=!DownLoaderThread.pause;
        if(DownLoaderThread.pause){
            btnpause.setText("繼續(xù)");
        }else{
            btnpause.setText("暫停");
        }
    }
}

private void addBars(List<DownLoaderInfo> list) {
    //添加進度條數(shù)組
    bars=new JProgressBar[list.size()];
    //循環(huán)所有的線程,創(chuàng)建進度條
    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++;
            //如果進度條的數(shù)量等于已下載的數(shù)量說明全下完了,就可以刪除進度條了
            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);
                        }
                        //首次下載后把元數(shù)據(jù)創(chuàng)建出來,并寫入到文件
                        creatMetaDate(downLoaderInfos);
                        //如果不是首次下載
                }else {
                        try {
                                File f = new File(location + ".meta");
                                prop = new Properties();
                                FileInputStream fis = new FileInputStream(f);
                                prop.load(fis);
                                //取出線程數(shù)
                                int count = Integer.parseInt(prop.getProperty("thread.count"));
                                for (int i=0;i<count;i++){
                                        //循環(huán)所有線程,取出重要數(shù)據(jù)
                                        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()+"");
                        //循環(huán)線程,把重要數(shù)據(jù)寫入到元數(shù)據(jù)文件
                        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;
        }

        //刪除元數(shù)據(jù)文件
        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問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI