• Java--多线程断点下载


    Main.java

    import java.net.HttpURLConnection;
    import java.net.URL;
    
    
    public class Main {
    	
    	private static Messages messages = new Messages();
    	
    	private static CallBack callback = new CallBack() {
    		@Override
    		public void schedule(Messages messages) {
    			long totalDownloadSize = messages.getTotalDownloadSize();
    			int currentDownloadSize = messages.getCurrentDownloadSize();
    			System.out.println((float)currentDownloadSize * 100.0f / (float)totalDownloadSize + "%");
    		}
    		
    		@Override
    		public void handlerMessages(Messages messages) {
    			
    		}
    		
    		@Override
    		public void fail(Messages messages) {
    			System.out.println(messages.getMsg());
    		}
    	};
    	
    	public static void main(String[] args) throws Exception {
    		long startTime = System.currentTimeMillis();
    		String downloadUrl = "http://www.xiazaiba.com/route.php?ct=stat&ac=stat_ads&id=CG8BOVNg&g=aHR0cDovL3d3dy51aWJpYS5jb20vamttc2V0dXAuZXhl";
    		URL url = new URL(downloadUrl);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setRequestMethod("GET");
    		conn.setReadTimeout(1000 * 5);
    		conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
    		conn.setRequestProperty("Accept-Language", "zh-CN");
    		conn.setRequestProperty("Referer", downloadUrl); 
    		conn.setRequestProperty("Charset", "UTF-8");
    		conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
    		conn.setRequestProperty("Connection", "Keep-Alive");
    		conn.connect();
    		
    		if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
    			FileDownloader loader = new FileDownloader(callback, 4, messages);
    			int size = conn.getContentLength();//根据响应获取文件大小
    			loader.setSavePath("E:\haoya.exe");
    			loader.setConfigPath("E:\haoya.properties");
    			loader.download(downloadUrl, size);
    		}else{
    			System.out.println(conn.getResponseCode());
    		}
    		
    		conn.disconnect();
    		long endTime = System.currentTimeMillis();
    		System.out.println("Time" + (endTime - startTime));
    	}
    }


    FileDownloader.java

    import java.io.File;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.net.URL;
    import java.util.Map;
    
    public class FileDownloader implements DownLoadCallBack {
    	//单个线程已经下载的长度
    	private int downloadSize;
    	//线程数 
    	private DownloadThread[] threads;
    	// 每条线程下载的长度 
    	private int block;
    	//文件保存路径
    	private String savePath;
    	//配置文件路径
    	private String configPath;
    	private File saveFile;
    	private boolean isNext;
    	private int call_curr;
    	private int call_total;
    	private PropertiesHelper propertiesHelper;    
    	private Map<String, String> datas;
    	private Messages messages;
    	private CallBack callback;
    	//总的下载长度
    	private int downloadLength;
    	//是否退出下载
    	private boolean exit;
    
    	public FileDownloader(CallBack callback, int threadNum, Messages messages) {
    		this.callback = callback;
    		this.threads = new DownloadThread[threadNum];
    		this.isNext = false;
    		this.call_total = threadNum;
    		this.downloadSize = 0;
    		this.downloadLength = 0;
    		this.messages = messages;
    		this.exit = false;
    	}
    
    	/**
    	 * 开始下载文件
    	 */
    	public void download(String downloadUrl, long size){
    		try {
    			messages.setTotalDownloadSize(size);
    			saveFile = new File(savePath);
    			RandomAccessFile accessFile = new RandomAccessFile(saveFile, "rw");
    			accessFile.setLength(size); 
    			accessFile.close();
    			
    			block = (int) ((size % this.threads.length) == 0 ? size
    					/ this.threads.length : size / this.threads.length + 1);
    			URL url = new URL(downloadUrl);
    
    			propertiesHelper = new PropertiesHelper(configPath); 
    			//如果配置文件不存在,则创建
    			if(!FileOperate.isFileExist(configPath)){
    				FileOperate.createFile(configPath, false);
    				initProperties();
    			}else{      
    				datas = propertiesHelper.getAllProperties();
    				if(datas.size() == 0) initProperties();
    			}   
    
    			for(int i = 0; i < threads.length; i++){
    				String value = datas.get(Constant.THREADID + (i + 1));
    				if(value == null) value = "0";
    				downloadSize = Integer.parseInt(value);  
    				downloadLength += downloadSize;
    			}
    
    			for (int i = 0; i < threads.length; i++) {// 开启线程进行下载 
    				String value = datas.get(String.valueOf(Constant.THREADID + (i + 1)));
    				if(value == null) value = "0";
    				downloadSize = Integer.parseInt(value);  
    				if(downloadSize == block){  
    					call_curr++;
    					if(call_curr == call_total){
    						isNext = true;
    						break;
    					}
    					continue;
    				}  
    				threads[i] = new DownloadThread(url, saveFile, block,  
    						downloadSize, i + 1, messages, callback, this);
    				threads[i].setPriority(7);
    				threads[i].start();
    			}
    			 
    			while(!isNext());
    		} catch (IOException e) { 
    			messages.setMsg("FileDownloader:download:" + e.getMessage());
    			callback.fail(messages);  
    		}
    	}   
    
    	private synchronized boolean isNext() {
    		return isNext;
    	}
    	
    	private void initProperties() {
    		for(int i = 0; i < threads.length; i++){
    			propertiesHelper.setProperties(Constant.THREADID + (i + 1), "0"); 
    		}
    		datas = propertiesHelper.getAllProperties();
    	}
    
    	@Override
    	public synchronized void isFinished() {
    		call_curr++;
    		if (call_curr == call_total){
    			isNext = true;
    		}
    	}
    
    	public synchronized void update(String key, String value){
    		propertiesHelper.setProperties(key, value);
    	}
    
    	@Override  
    	public synchronized int getDownloadLength() {
    		return downloadLength;
    	}
    
    	@Override
    	public synchronized void append(int size) {
    		downloadLength += size;
    	}
    
    	public String getSavePath() {
    		return savePath;
    	}
    
    	public void setSavePath(String savePath) {
    		this.savePath = savePath;
    	}
    
    	public String getConfigPath() {
    		return configPath;
    	}
    
    	public void setConfigPath(String configPath) {
    		this.configPath = configPath;
    	}
    
    	@Override
    	public boolean getExit() {
    		return exit;
    	}
    
    	@Override
    	public void setExit(boolean isExit) {
    		exit = isExit;
    	}
    }
    


    DownloadThread.java

    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class DownloadThread extends Thread {
    	private File saveFile;
    	private URL downUrl;
    	private int block;
    	private int threadId = -1;    
    	private CallBack callback;
    	private DownLoadCallBack downLoadCallBack;
    	private int downloadSize;
    	private Messages messages; 
    
    	public DownloadThread(URL downUrl, File saveFile, int block, int downloadSize, int threadId, Messages messages, CallBack callback, DownLoadCallBack downLoadCallBack) {
    		this.downLoadCallBack = downLoadCallBack;
    		this.downUrl = downUrl;
    		this.saveFile = saveFile;
    		this.block = block;
    		this.threadId = threadId;
    		this.callback = callback;
    		this.downloadSize = downloadSize;
    		this.messages = messages;
    	}
    
    	@Override
    	public void run() {
    		HttpURLConnection conn = null;
    		InputStream inStream = null;
    		RandomAccessFile threadfile = null;   
    		try {  
    			conn = (HttpURLConnection) downUrl.openConnection();
    			conn.setRequestMethod(Constant.GET);
    			conn.setReadTimeout(1000 * 8);
    			int startPos = block * (threadId - 1) + downloadSize;//开始位置   
    			int endPos = block * threadId -1;//结束位置  
    			conn.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围
    
    			if(conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
    				inStream = conn.getInputStream();   
    				byte[] buffer = new byte[Constant.BUFFER * 10];
    				int offset = 0;
    				threadfile = new RandomAccessFile(saveFile, "rwd");  
    				threadfile.seek(startPos);
    				String key = Constant.THREADID + String.valueOf(threadId);  
    				//messages,文件总大小,下载的当前大小
    				while (!downLoadCallBack.getExit() && (offset = inStream.read(buffer)) != -1) {   
    					threadfile.write(buffer, 0, offset);   
    					downLoadCallBack.append(offset);      
    					downloadSize += offset;
    					downLoadCallBack.update(key, String.valueOf(downloadSize));
    					int size = downLoadCallBack.getDownloadLength();
    					messages.setCurrentDownloadSize(size);
    					callback.schedule(messages);   
    				}
    			}
    		} catch (IOException e) {
    			downLoadCallBack.setExit(true);
    			messages.setMsg("第" + threadId + "条线程下载失败"); 
    			callback.fail(messages);   
    		}finally{ 
    			try {
    				if(threadfile != null){
    					threadfile.close();  
    				}
    				if(inStream != null){  
    					inStream.close();
    				} 
    				if(conn != null){
    					conn.disconnect();
    				}
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			downLoadCallBack.isFinished();
    		}
    	}
    }
    



    DownLoadCallBack.java

    public interface DownLoadCallBack {
    	public void isFinished();
    	
    	public void update(String key, String value);
    	
    	public void append(int size);
    	
    	public int getDownloadLength();
    	
    	public boolean getExit();
    	
    	public void setExit(boolean isExit);
    }
    


    CallBack.java

    public interface CallBack {
    	
    	public void handlerMessages(Messages messages);
    	
    	public void schedule(Messages messages);
    	
    	public void fail(Messages messages);
    }
    


    FileOperate.java

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    public class FileOperate {
    	/**
    	 * 在指定路径下创建新文件
    	 * @param filePath      文件路径
    	 * @return
    	 * @throws IOException
    	 */
    	public static File createFile(String filePath, boolean isDeleteAllFiles) {
    		String parentPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
    		createFolders(parentPath, isDeleteAllFiles);
    		File file = new File(filePath);
    		try {
    			if(!file.createNewFile()){
    				file.delete();
    				file.createNewFile();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return file;
    	}
    
    	/**
    	 * 判断配置文件是否存在
    	 * @param filePath  文件路径
    	 * @return
    	 */
    	public static boolean isFileExist(String filePath){
    		File file = new File(filePath);
    		return file.exists();
    	}
    
    	/**
    	 * 取得指定目录下的所有文件夹名
    	 * @return
    	 */
    	public static List<String> getFilesName(String filePath){
    		List<String> files_name = null;
    		File file = new File(filePath);
    		if(file.exists()){
    			files_name = new ArrayList<String>();
    			File[] files = file.listFiles();
    			for (File file2 : files) {
    				if(file2.isDirectory()){
    					files_name.add(file2.getName());
    				}
    			}
    		}
    		return files_name;
    	}
    
    	public static void deleteFiles(File file){
    		if(file.exists()){
    			File[] files = file.listFiles();
    			for(File f : files){
    				if(f.isFile()) f.delete();
    			}
    		}
    	}
    
    	public static File createFolders(String path, boolean isDeleteAllFiles){
    		File file = new File(path);
    		if(file.exists() && file.isDirectory()){
    			if(isDeleteAllFiles) deleteFiles(file);
    		}else{
    			file.mkdirs();
    		}
    		return file;
    	}
    
    	public static boolean deleteFile(String filePath){
    		boolean isDeleted = false;
    		File file = new File(filePath);
    		if(file.exists()){
    			if(file.isFile()) {
    				file.delete();
    				isDeleted = true;
    			}
    		}
    		return isDeleted;
    	}
    
    	public static void deleteMkdir(String filePath){
    		File file = new File(filePath);
    		if(file.exists() && file.isDirectory()){
    			file.delete();
    		}
    	}
    
    
    	/*********删除文件夹******/
    	public static boolean deleteFolders(String filePath){
    		boolean isDeleteSuccess = false;
    		LinkedList<String> folderList = new LinkedList<String>();
    		folderList.add(filePath);
    
    		while(folderList.size() > 0){
    			File file1 = new File(folderList.poll());
    			File[] files1 = file1.listFiles();
    			ArrayList<File> fileList = new ArrayList<File>();
    			for(int i = 0; i < fileList.size(); i++){
    				if(files1[i].isDirectory()){
    					folderList.add(files1[i].getPath());
    				}else{
    					fileList.add(files1[i]);
    				}
    			}
    			//删除文件
    			for(File file : fileList){
    				file.delete();
    			}
    		}
    
    		//删除文件夹
    		folderList = new LinkedList<String>();
    		folderList.add(filePath);
    		while(folderList.size() > 0){
    			File file2 = new File(folderList.getLast());
    			if(file2.delete()){
    				folderList.removeLast();
    			}else{
    				File[] files2 = file2.listFiles();
    				for(int i = 0; i < files2.length; i++){
    					folderList.add(files2[i].getPath());
    				}
    			}
    		}
    		if(folderList.size() == 0) isDeleteSuccess = true;
    		return isDeleteSuccess;
    	}
    
    	public static boolean moveFile(String srcFilePath, String dstFilePath){
    		boolean isMoveFileSuccess = false;
    		
    		BufferedInputStream bis = null;
    		BufferedOutputStream bos = null;
    		FileInputStream fis = null;
    		FileOutputStream fos = null;
    		try {
    			if(isFileExist(dstFilePath)) deleteFile(dstFilePath);
    			File dstFile = createFile(dstFilePath, false);
    			fis = new FileInputStream(new File(srcFilePath));
    			fos = new FileOutputStream(dstFile);
    			bis = new BufferedInputStream(fis);
    			bos = new BufferedOutputStream(fos, Constant.BUFFER * 10);
    			int count = -1;
    			byte[] buffer = new byte[Constant.BUFFER * 10];
    			while((count = bis.read(buffer, 0, Constant.BUFFER * 10)) != -1){
    				bos.write(buffer, 0, count);
    				bos.flush();
    			}
    			isMoveFileSuccess = true;
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}finally{
    			try {
    				if(bos != null){
    					bos.close();
    				}
    				if(fos != null){
    					fos.close();
    				}
    				if(bis != null){
    					bis.close();
    				}
    				if(fis != null){
    					fis.close();
    				}
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		return isMoveFileSuccess;
    	}
    }
    



    Constant.java

    public class Constant {
    	public static final int BUFFER = 1024;
    	public static final String UTF = "utf-8";
    	public static final String THREADID = "threadId";  
    	
    	public static final String OGG = ".ogg";
    	public static final String PACK = ".pack";
    	public static final String PNG = ".png";
    	public static final String MP3 = ".mp3";
    	public static final String PROPERTIES = ".properties";
    	public static final String TMX = ".tmx";
    	public static final String GET = "GET";
    }
    


    Messages.java

    public class Messages {
    	private String msg;
    	private long totalDownloadSize;
    	private int currentDownloadSize;
    	public String getMsg() {
    		return msg;
    	}
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    	public long getTotalDownloadSize() {
    		return totalDownloadSize;
    	}
    	public void setTotalDownloadSize(long totalDownloadSize) {
    		this.totalDownloadSize = totalDownloadSize;
    	}
    	public int getCurrentDownloadSize() {
    		return currentDownloadSize;
    	}
    	public void setCurrentDownloadSize(int currentDownloadSize) {
    		this.currentDownloadSize = currentDownloadSize;
    	}
    }


    PropertiesHelper.java

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    public class PropertiesHelper {
    
    	private String project_root = "";
    
    	public PropertiesHelper(String filePath) {
    		if (filePath != null && filePath.length() > 0) {
    			project_root = project_root + filePath;
    		}
    	}
    
    	public String getProperties(String key) {
    		InputStream fis = null;
    		try {
    			Properties prop = new Properties();
    			fis = new FileInputStream(project_root);
    			prop.load(fis);
    			return prop.getProperty(key);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (fis != null)
    					fis.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return null;
    	}
    
    	public Map<String, String> getAllProperties() {
    		InputStream fis = null;
    		Map<String, String> params = new HashMap<String, String>();
    		try {
    			Properties prop = new Properties();
    			fis = new FileInputStream(project_root);
    			prop.load(fis);
    			Enumeration en = prop.propertyNames();
    			while (en.hasMoreElements()) {
    				String key = (String) en.nextElement();
    				String value = prop.getProperty(key);
    				params.put(key, value);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (fis != null)
    					fis.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return params;
    	}
    
    	public void setProperties(String key, String value) {
    		Properties prop = new Properties();
    		FileOutputStream outputFile = null;
    		InputStream fis = null;
    		try {
    			// 输入流和输出流要分开处理, 放一起会造成写入时覆盖以前的属性
    			fis = new FileInputStream(project_root);
    			// 先载入已经有的属性文件
    			prop.load(fis);
    
    			// 追加新的属性
    			prop.setProperty(key, value);
    
    			// 写入属性
    			outputFile = new FileOutputStream(project_root);
    			prop.store(outputFile, "");
    
    			outputFile.flush();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (fis != null)
    					fis.close();
    				if (outputFile != null)
    					outputFile.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    



  • 相关阅读:
    DISTINCT 方法用于返回唯一不同的值 。
    UNION操作用于合并两个或多个 SELECT 语句的结果集。
    JOIN方法也是连贯操作方法之一
    HAVING方法也是连贯操作之一
    GROUP方法也是连贯操作方法之一
    page方法也是模型的连贯操作方法之一
    limit方法也是模型类的连贯操作方法之一
    order方法属于模型的连贯操作方法之一
    field方法属于模型的连贯操作方法之一
    data方法也是模型类的连贯操作方法之一,
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3258062.html
Copyright © 2020-2023  润新知