java中怎么利用多線程實現(xiàn)文件下載功能,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
宜豐ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!
1、DownloadManager類
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.List; public class DownloadManager implements Runnable { // 保存路徑 private String savePath; // 總的下載線程數(shù) private int threadNum; // 下載的鏈接地址 private String urlFile; // 是否下載開始 private boolean isStarted; // 用于監(jiān)視何時合并文件存放Thread的list private List<DownloadThread> downloadList = new ArrayList<DownloadThread>(); public DownloadManager(String savePath, int threadNum, String urlFile) { super(); this.savePath = savePath; this.threadNum = threadNum; this.urlFile = urlFile; } // 最終調(diào)用線程下載。本線程中調(diào)用分線程。 public void action() { new Thread(this).start(); } public void run() { long t1 = System.currentTimeMillis(); System.out.println(t1); // 如果沒有下載 , 就開始 , 并且將已經(jīng)下載的變量值設(shè)為true if (!isStarted) { startDownload(); isStarted = true; } while (true) { // 初始化認為所有線程下載完成,逐個檢查 boolean finish = true; // 如果有任何一個沒完成,說明下載沒完成,不能合并文件 for (DownloadThread thread : downloadList) { if (!thread.isFinish()) { finish = false; break; } } // 全部下載完成才為真 if (finish) { // 合并文件 mergeFiles(); // 跳出循環(huán) , 下載結(jié)束 break; } // 休息一會 , 減少cpu消耗 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } long t2 = System.currentTimeMillis(); System.out.println(t2); System.out.println("下載用時:" + (t2 -t1)); } public void startDownload() { // 得到每個線程開始值 , 下載字節(jié)數(shù)大小 int[][] posAndLength = getPosAndLength(); // 根據(jù)下載信息創(chuàng)建每個下載線程,并且啟動他們。 for (int i = 0; i < posAndLength.length; i++) { int pos = posAndLength[i][0]; int length = posAndLength[i][1]; DownloadThread downloadThread = new DownloadThread(i + 1, length, pos, savePath, urlFile); new Thread(downloadThread).start(); downloadList.add(downloadThread); } } /** * 獲得文件大小 * * @return 文件大小 */ public long getFileLength() { System.out.println("獲得文件大小 start......"); HttpURLConnection conn = null; long result = 0; try { URL url = new URL(urlFile); conn = (HttpURLConnection) url.openConnection(); // 使用Content-Length頭信息獲得文件大小 result = Long.parseLong(conn.getHeaderField("Content-Length")); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); } } System.out.println("獲得文件大小 end......" + result); return result; } // 具體細節(jié)求出每個線程的開始位置和文件下載大小 public int[][] getPosAndLength() { int[][] result = new int[threadNum][2]; int fileLength = (int) getFileLength(); int every = fileLength % threadNum == 0 ? fileLength / threadNum : fileLength / threadNum + 1; for (int i = 0; i < result.length; i++) { int length = 0; if (i != result.length - 1) { length = every; } else { length = fileLength - i * every; } result[i][0] = i * every; result[i][1] = length; } return result; } // 合并文件 public void mergeFiles() { System.out.println("合并文件 start......"); OutputStream out = null; try { out = new FileOutputStream(savePath); for (int i = 1; i <= threadNum; i++) { InputStream in = new FileInputStream(savePath + i); byte[] bytes = new byte[2048]; int read = 0; while ((read = in.read(bytes)) != -1) { out.write(bytes, 0, read); out.flush(); } if (in != null) { in.close(); new File(savePath + i).delete(); } } } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("合并文件 end......"); } public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } public int getThreadNum() { return threadNum; } public void setThreadNum(int threadNum) { this.threadNum = threadNum; } public String getUrlFile() { return urlFile; } public void setUrlFile(String urlFile) { this.urlFile = urlFile; } public boolean isStarted() { return isStarted; } public void setStarted(boolean isStarted) { this.isStarted = isStarted; } public List<DownloadThread> getDownloadList() { return downloadList; } public void setDownloadList(List<DownloadThread> downloadList) { this.downloadList = downloadList; }}
2、DownloadThread類
import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL; public class DownloadThread implements Runnable { // 當前第幾個線程 , 用于給下載文件起名 file1 file2 file3 ... private int whichThread; // 監(jiān)聽單一線程下載是否完成 private boolean isFinish; // 本線程要下載的文件字節(jié)數(shù) private int length; // 本線程向服務(wù)器發(fā)送請求時輸入流的首位置 private int startPosition; // 保存的路徑 private String savePath; // 要下載的文件 , 用于創(chuàng)建連接 private String url; public void run() { HttpURLConnection conn = null; InputStream in = null; OutputStream out = null; try { System.out.println("正在執(zhí)行的線程:" + whichThread); URL fileUrl = new URL(url); // 與服務(wù)器創(chuàng)建連接 conn = (HttpURLConnection) fileUrl.openConnection(); // 下載使用get請求 conn.setRequestMethod("GET"); // 告訴服務(wù)器 , 我是火狐 , 不要不讓我下載。 conn.setRequestProperty( "User-Agent", "Firefox Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3"); // 這里是設(shè)置文件輸入流的首位置 conn.setRequestProperty("Range", "bytes=" + startPosition + "-"); // 與服務(wù)器創(chuàng)建連接 conn.connect(); // 獲得輸入流 in = conn.getInputStream(); // 在硬盤上創(chuàng)建file1 , file2 , ...這樣的文件 , 準備往里面寫東西 out = new FileOutputStream(savePath + whichThread); // 用于寫入的字節(jié)數(shù)組 byte[] bytes = new byte[4096]; // 一共下載了多少字節(jié) int count = 0; // 單次讀取的字節(jié)數(shù) int read = 0; while ((read = in.read(bytes)) != -1) { // 檢查一下是不是下載到了本線程需要的長度 if (length - count < bytes.length) { // 比如說本線程還需要900字節(jié),但是已經(jīng)讀取1000 // 字節(jié),則用要本線程總下載長度減去 // 已經(jīng)下載的長度 read = length - count; } // 將準確的字節(jié)寫入輸出流 out.write(bytes, 0, read); // 已經(jīng)下載的字節(jié)數(shù)加上本次循環(huán)字節(jié)數(shù) count = count + read; // 如果下載字節(jié)達到本線程所需要字節(jié)數(shù),消除循環(huán), // 停止下載 if (count == length) { break; } } // 將監(jiān)視變量設(shè)置為true isFinish = true; } catch (Exception e) { e.printStackTrace(); } finally { // 最后進行輸入、輸出、連接的關(guān)閉 if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if (conn != null) { conn.disconnect(); } } } public int getStartPosition() { return startPosition; } public void setStartPosition(int startPosition) { this.startPosition = startPosition; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getWhichThread() { return whichThread; } public void setWhichThread(int whichThread) { this.whichThread = whichThread; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } public DownloadThread(int whichThread, int length, int startPosition, String savePath, String url) { super(); this.whichThread = whichThread; this.length = length; this.startPosition = startPosition; this.savePath = savePath; this.url = url; } public DownloadThread() { super(); } public boolean isFinish() { return isFinish; } public void setFinish(boolean isFinish) { this.isFinish = isFinish; }}
3、TestDownload測試類
public class TestDownload { public static void main(String[] args) { DownloadManager downloadManager = new DownloadManager("d:/upload/09018417.zip" , 5 , "http://10.1.2.65:8080/cetvossFront/09018417.zip"); downloadManager.action(); }}
看完上述內(nèi)容,你們掌握java中怎么利用多線程實現(xiàn)文件下載功能的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
新聞標題:java中怎么利用多線程實現(xiàn)文件下載功能
瀏覽地址:http://jinyejixie.com/article42/pgeghc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、全網(wǎng)營銷推廣、做網(wǎng)站、面包屑導(dǎo)航、軟件開發(fā)、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)