精华内容
下载资源
问答
  • java实现多线程下载文件功能,通过线程池管理,实现下载文件速度快,安全。
  • Java多线程实现复制文件

    千次阅读 2018-09-24 15:55:33
    * 多线程实现文件从一个目录复制到另一个目录 * @param sourceFile:给定源文件路径名 * @param desPath:复制点文件路径 * @return */ 代码实现如下: package com.tulun.thread; import java.io.File; import...
    /**
     * 实现文件复制功能
     * 多线程实现文件从一个目录复制到另一个目录
     * @param sourceFile:给定源文件路径名
     * @param desPath:复制点文件路径
     * @return
     */
    

    代码实现如下:

    package com.tulun.thread;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.RandomAccessFile;
    
    /**
     * 多线程复制文件
     */
    public class ThreadCopyFile {
        public static void main(String[] args) throws Exception {
            File file = new File("D:\\demo\\erke\\test.txt");
            startThread(5, file.length(), "D:\\demo\\erke\\test.txt",
                    "D:\\demo\\erke\\test1.txt");
        }
    
        /**
         * 开启多线程复制
         * 
         * @param threadnum   线程数
         *  
         * @param fileLength   文件大小(用于确认每个线程下载多少东西)
         *            
         * @param sourseFilePath    源文件目录
         *           
         * @param desFilePath     目标文件目录
         *           
         */
        public static void startThread(int threadnum, long fileLength, String sourseFilePath, String desFilePath) {
            System.out.println(fileLength);
            long modLength = fileLength % threadnum;
            System.out.println("modLength:" + modLength);
            long desLength = fileLength / threadnum;
            System.out.println("desLength:" + desLength);
            for (int i = 0; i < threadnum; i++) {
                System.out.println((desLength * i) + "-----" + (desLength * (i + 1)));
                new FileWriteThread((desLength * i), (desLength * (i + 1)), sourseFilePath, desFilePath).start();
            }
            if (modLength != 0) {
                System.out.println("最后的文件写入");
                System.out.println((desLength * threadnum) + "-----" + (desLength * threadnum + modLength));
                new FileWriteThread((desLength * threadnum), desLength * threadnum + modLength + 1, sourseFilePath,
                        desFilePath).start();
            }
        }
    
        /**
         * 写线程:指定文件开始位置、目标位置、源文件、目标文件,
         */
        static class FileWriteThread extends Thread {
            private long begin;
            private long end;
            private RandomAccessFile sourseFile;
            private RandomAccessFile desFile;
    
            public FileWriteThread(long begin, long end, String sourseFilePath, String desFilePath) {
                this.begin = begin;
                this.end = end;
                try {
                    this.sourseFile = new RandomAccessFile(sourseFilePath, "rw");
                    this.desFile = new RandomAccessFile(desFilePath, "rw");
                } catch (FileNotFoundException e) {
                }
            }
    
            public void run() {
                try {
                    sourseFile.seek(begin);
                    desFile.seek(begin);
                    int hasRead = 0;
                    byte[] buffer = new byte[1];
                    while (begin < end && -1 != (hasRead = sourseFile.read(buffer))) {
                     	begin += hasRead;
                        desFile.write(buffer, 0, hasRead);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        sourseFile.close();
                        desFile.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
    
    

    运行结果:
    在这里插入图片描述

    展开全文
  • Java多线程使用线程池实现文件下载

    千次阅读 2018-11-21 11:08:35
    多线程下载原理: 1、基本思路是将文件分段切割、分段传输、分段保存。 2、分段切割用到HttpUrlConnection对象的setRequestProperty(“Range”, “bytes=” + start + “-” + end)方法。 3、分段传输用到...

    多线程下载原理:

    1、基本思路是将文件分段切割、分段传输、分段保存。

    2、分段切割用到HttpUrlConnection对象的setRequestProperty(“Range”, “bytes=” + start + “-” + end)方法。

    3、分段传输用到HttpUrlConnection对象的getInputStream()方法。

    4、分段保存用到RandomAccessFile的seek(int start)方法。

    5、创建指定长度的线程池,循环创建线程,执行下载操作。

    代码设计:

    总共代码分为三个类,DownloadWithRange 、DownloadFileWithThreadPool和test。其中test相当于实际使用中框架中的controll层代码。DownloadWithRange 实现Runnable接口,DownloadFileWithThreadPool主要是线程池操作和调用DownloadWithRange 类。test就是一个测试类。

    package file;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    /**
     *   2018/11/21.
     */
    public class DownloadWithRange implements Runnable
    {
        private String urlLocation;
    
        private String filePath;
    
        private long start;
    
        private long end;
    
        DownloadWithRange(String urlLocation, String filePath, long start, long end)
        {
            this.urlLocation = urlLocation;
            this.filePath = filePath;
            this.start = start;
            this.end = end;
        }
    
        @Override
        public void run()
        {
            try
            {
                HttpURLConnection conn = getHttp();
                conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
    
                File file = new File(filePath);
                RandomAccessFile out = null;
                if (file != null)
                {
                    out = new RandomAccessFile(file, "rwd");
                }
                out.seek(start);
                InputStream in = conn.getInputStream();
                byte[] b = new byte[1024];
                int len = 0;
                while ((len = in.read(b)) != -1)
                {
                    out.write(b, 0, len);
                }
                in.close();
                out.close();
            }
            catch (Exception e)
            {
                e.getMessage();
            }
    
        }
    
        public HttpURLConnection getHttp() throws IOException
        {
            URL url = null;
            if (urlLocation != null)
            {
                url = new URL(urlLocation);
            }
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
    
            return conn;
        }
    
    }
    
    package file;
    
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.concurrent.Executor;
    import java.util.concurrent.Executors;
    /**
     *   2018/11/21.
     */
    public class DownloadFileWithThreadPool
    {
        public void getFileWithThreadPool(String urlLocation,String filePath, int poolLength) throws IOException
        {
            Executor threadPool = Executors.newFixedThreadPool(poolLength);
            
            long len = getContentLength(urlLocation);
            System.out.println("文件大小:"+len);
            for(int i=0;i<poolLength;i++)
            {
                long start=i*len/poolLength;
                long end = (i+1)*len/poolLength-1;
                if(i==poolLength-1)
                {
                    end =len;
                }
                DownloadWithRange download=new DownloadWithRange(urlLocation, filePath, start, end);
                threadPool.execute(download);
                try {
    				Thread.sleep(2);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
            }
        }
    
        public static long getContentLength(String urlLocation) throws IOException
        {
            URL url = null;
            if (urlLocation != null)
            {
                url = new URL(urlLocation);
            }
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            long len = conn.getContentLength();
    
            return len;
        }
    }
    
    
    package file;
    
    import java.io.IOException;
    
    
    
    public class test {
    	 public static  void main(String [] args){
    		 DownloadFileWithThreadPool dfw = new DownloadFileWithThreadPool();
    		 try {  // "http://10.128.99.13"+"/usr/ulitech/dataroot/scadadata/2018/11.tar.gz"
    			 long startTime=System.currentTimeMillis(); 
    			 dfw.getFileWithThreadPool("http://10.128.99.13:8080"+"/sysobjects/sysobjects.db","E:/1/11.rar",10);
    			 long endTime=System.currentTimeMillis();  
    			 System.out.println("耗费时间: "+(endTime-startTime)+" ms");
    			 System.out.println("下载成功!");
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	    }
    }
    

    思考:

    1.对于下载路径处理?路径的有效性?
    2.多个小文件的效率?
    后续进行分析和解答。。。。。。。。。。

    展开全文
  • 上一篇中说的是单线程实现的文件上传,接下来说说多线程实现文件上传 首先搞清楚应该是对于服务器端的多线程,因为是多个客户端同时向服务器端上传 编写客户端代码,先读取本地文件,然后给服务器端发送数据,最后...

    上一篇中说的是单线程实现的文件上传,接下来说说多线程实现文件上传

    首先搞清楚应该是对于服务器端的多线程,因为是多个客户端同时向服务器端上传

    编写客户端代码,先读取本地文件,然后给服务器端发送数据,最后接收一下是否上传成功

    //实现图片上传的客户端
            Socket socket = new Socket(InetAddress.getByName("10.0.185.144"),44444);
    
            //读取本地图片的字节读取流
    		FileInputStream fis = new FileInputStream("new.jpg");
    
    		//给服务器端发送数据的字节输出流
    		OutputStream out = socket.getOutputStream();
    
    		//读取"上传成功"的字节读取流
    		InputStream in = socket.getInputStream();
    
    		//循环读取本地图片,发送给服务器端
    		byte[] arr = new byte[1024];
    		int len = 0;
    		while((len = fis.read(arr))!=-1)
    		{
    			out.write(arr,0,len);
    		}
    		//向服务器写入结束标记
    		socket.shutdownOutput();
    
    		//读取"上传成功"
            int num = in.read(arr);
    		System.out.println(new String(arr,0,num));
    
    		fis.close();
    		socket.close();

    接下来是服务器端

    首先要创建一个实现了Runnable或者继承了Thread(因为实现Runnable的方式,线程和线程任务是分离的,所以我使的是这种方式)的类将每次都要执行的代码写到run方法中,然后创建一个线程去执行就可以了

    class PicUpload implements Runnable 
    {
    	private Socket socket;
    	public PicUpload(Socket socket)
    	{
    		this.socket = socket;
    	}
    
    	public void run()
    	{
    		try{
    			//把上传的图片放到统一的目录下
    			File dir = new File("pictures");
    			if(!dir.exists())
    				dir.mkdir();
    
    			String ip = socket.getInetAddress().getHostAddress();
    			System.out.println(ip+"连接到客户端");
                
    			int num = 0;
                            File file = new File(dir,ip+(++num)+".jpg");
    
    			while(file.exists())
    			{
    				file = new File(dir,ip+(++num)+".jpg");
    			}
    
    			FileOutputStream fos = new FileOutputStream(file);
    			InputStream  in = socket.getInputStream();
    			OutputStream out = socket.getOutputStream();
    
    			byte[] arr = new byte[1024];
    			int len = 0;
    			while((len = in.read(arr))!=-1)
    			{
    				fos.write(arr,0,len);
    			}
    			fos.close();
    
    			out.write("上传成功".getBytes());
    			socket.close();
    		}
            catch(Exception e)
    		{
    			e.printStackTrace();
    		}
    	}
    }

    写一下服务器端
    class Test 
    {
    	public static void main(String[] args)throws IOException 
    	{
    		ServerSocket server = new ServerSocket(44444);
    
            while(true)
    		{
    			Socket socket = server.accept();
    			new Thread(new PicUpload(socket)).start();
    		}
    
    	}
    }
    这样就可以实现多个客户端同时向服务器端上传文件了


    展开全文
  • Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
  • OSS实现文件多线程的断点下载java) 所谓断点下载,就是要从文件已经下载的地方开始继续下载,对于断点续传这样有状态功能的实现,关键点在于如何在客户端完成状态维护。此篇主要介绍多文件多线程的断点下载

    OSS实现多文件多线程的断点下载(java)

    本文地址:http://blog.csdn.net/zrk1000/article/details/46286767

    开放存储服务(Open Storage Service,OSS),是阿里云对外提供的海量、安全和高可靠的云存储服务,目前越来越多的开发者将应用数据存放至OSS,对使用OSS实现文件的断点续传功能使用的也比较多,在这儿分享下自己使用OSS的实例。

    所谓断点下载,就是要从文件已经下载的地方开始继续下载,对于断点续传这样有状态功能的实现,关键点在于如何在客户端完成状态维护。此篇主要介绍多文件的多线程的断点下载。

    为了限定同时下载文件的个数和每个文件同时下载的线程数,使用了线程池嵌套线程池来完成,外层线程池downloadMainPool用来限定并发下载的文件数,内层线程池pool执行单个文件的多线程下载。

    downloadMainPool 代码片段:

        public static ExecutorService downloadMainPool = null;
        static{
            downloadMainPool = Executors.newFixedThreadPool(Constant.CONCURRENT_FILE_NUMBER,new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    Thread s = Executors.defaultThreadFactory().newThread(r);
                    s.setDaemon(true);
                    return s;
                }
            });
        }

    在static中实例化为固定大小的线程池,由于默认的ThreadFactory创建的线程为非守护状态,为了避免java程序不能退出的问题,保证在文件下载完后当前java程序结束在jvm中的运行,需要重写ThreadFactory,使其创建的线程为守护线程。

    Constant类中自定义了程序中需要使用到的变量,可在类中直接定义或读取配置文件,Constant.CONCURRENT_FILE_NUMBER定义了并发文件数。

    downloadMainPool中的每个线程负责一个文件,每个线程下载文件时创建子线程池,由子线程池分块下载文件;要做到断点续传需要记录每个子线程池中的每个线程下载位置,这里使用定时序列化子线程池线程对象的方式,定时将包含了下载位置的线程序列化到文件,在再次下载同一文件时反序列化,直接丢到子线程池下载即可。下面是downloadMainPool中的线程OSSDownloadFile代码清单

    OSSDownloadFile 代码:

    package cloudStorage.oss;
    
    import java.io.File;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    import org.apache.log4j.Logger;
    import cloudStorage.basis.Constant;
    import cloudStorage.basis.Global;
    import cloudStorage.basis.OSSClientFactory;
    import cloudStorage.oss.download.DownloadPartObj;
    import cloudStorage.oss.download.DownloadPartThread;
    import cloudStorage.util.ObjectSerializableUtil;
    
    import com.aliyun.oss.OSSClient;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.ObjectMetadata;
    
    /**
     * @Description: oss多线程分段下载文件
     * @author: zrk
     * @time: 2015年4月1日 上午10:37:35
     */
    public class OSSDownloadFile  implements Callable<Integer>{
        public static final Logger LOGGER = Logger.getLogger(OSSDownloadFile.class);
        //外层线程池
        public static ExecutorService downloadMainPool = null;
        //内层线程池
        private ExecutorService pool ;
    
        static{
            downloadMainPool = Executors.newFixedThreadPool(Constant.CONCURRENT_FILE_NUMBER,new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    Thread s = Executors.defaultThreadFactory().newThread(r);
                    s.setDaemon(true);
                    return s;
                }
            });
        }
        private String localFilePath;//本地文件路径
        private String bucketName; //bucketName
        private String key;//云端存储路径
    
        public OSSDownloadFile() {
            super();
        }
    
        public OSSDownloadFile(String localFilePath,String bucketName,String key) {
            //初始化子线程池
            pool = Executors.newFixedThreadPool(Constant.SINGLE_FILE_CONCURRENT_THREADS);
            this.localFilePath = localFilePath;
            this.bucketName = bucketName;
            this.key = key;
    
        }
    
        //执行当前线程
        public Integer downloadFile() {
            Integer r = Global.ERROR;
            //向downloadMainPool中submit当前线程
            Future<Integer> result = downloadMainPool.submit(this);
            try {
                r=result.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            } finally{
                return r;
            }
    
        }
        /**
         * 
         * @param localFilePath     需要存放的文件路径
         * @param bucketName        bucketName
         * @param key               存储key  -在oss的存储路径
         * @return
         */
        @Override
        public Integer call(){
            //OSSClient 使用单例
            OSSClient client = OSSClientFactory.getInstance();    
            ObjectMetadata objectMetadata = null;
            //判断文件在云端是否存在
            try {
                objectMetadata = client.getObjectMetadata(bucketName, key);
            } catch (OSSException e) {
                LOGGER.info("==请检查bucketName或key");
                return Global.ERROR;
            }
            long fileLength = objectMetadata.getContentLength();
    
            //自定义的每个下载分块大小
            Integer partSize = Constant.DOWNLOAD_PART_SIZE;
    
            //需要下载的文件分块数
            int partCount=calPartCount(fileLength, partSize);
    
            //子线程池的线程对象封装类(用于序列化的)
            DownloadPartObj downloadPartObj = null;
            boolean isSerializationFile = false;
            //序列化的文件路径(与下载文件同路径使用.dw.temp后缀)
            String serializationFilePath = localFilePath+".dw.temp";
            //若存在反序列化对象
            if(new File(serializationFilePath).exists()){
                downloadPartObj = (DownloadPartObj)ObjectSerializableUtil.load(serializationFilePath);
                isSerializationFile = true;
            }
            //序列化文件不存在,分配分块给子线程池线程对象
            if(downloadPartObj==null||!isSerializationFile){
                downloadPartObj = new DownloadPartObj();
                for (int i = 0; i < partCount; i++) {
                      final  long startPos = partSize * i;
                      final  long endPos = partSize * i +( partSize < (fileLength - startPos) ? partSize : (fileLength - startPos)) - 1;
                      //DownloadPartThread是执行每个分块下载任务的线程
                      downloadPartObj.getDownloadPartThreads().add(new DownloadPartThread(startPos, endPos, localFilePath, bucketName, key,Constant.ACCESS_ID,Constant.ACCESS_KEY));
                    }
            }
    
            try {
                int i = 0;
                //download方法提交分块下载线程至子线程池下砸,while循环用于下载失败重复下载,Constant.RETRY定义重复下载次数
                while (download(downloadPartObj,serializationFilePath).isResult()==false) {
                    if(++i == Constant.RETRY)break;
                    LOGGER.info(Thread.currentThread().getName()+"重试第"+i+"次");
                }
            } catch (Exception e) {
                LOGGER.info("=="+e.getMessage());
                return Global.THREAD_ERROR;
            }
            if(!downloadPartObj.isResult()){
                return Global.NETWORK_ERROR;
            }
            return Global.SUCCESS;
        }
    
    
        /**
         *  多线程下载单个文件
         * @param partThreadObj
         * @param serializationFilePath
         * @return
         */
        private DownloadPartObj download(DownloadPartObj partThreadObj,String serializationFilePath){
    
            try {
                partThreadObj.setResult(true);
                //向子线程池中submit单个文件所有分块下载线程
                for (int i=0 ;i<partThreadObj.getDownloadPartThreads().size();i++) {
                    if (partThreadObj.getDownloadPartThreads().get(i).geteTag() == null)
                        pool.submit(partThreadObj.getDownloadPartThreads().get(i));
                }
                //shutdown子线程池,池内所下载任务执行结束后停止当前线程池
                pool.shutdown();
                //循环检查线程池,同时在此序列化partThreadObj
                while (!pool.isTerminated()) {
                    ObjectSerializableUtil.save(partThreadObj,serializationFilePath);
                    pool.awaitTermination(Constant.SERIALIZATION_TIME, TimeUnit.SECONDS);
                }
                //判断下载结果
                for (DownloadPartThread downloadPartThread: partThreadObj.getDownloadPartThreads()) {
                    if (downloadPartThread.geteTag() == null){
                        partThreadObj.setResult(false);
                    }
                }
                //下载成功 删除序列化文件
                if (partThreadObj.isResult()==true) 
                    ObjectSerializableUtil.delSerlzFile(serializationFilePath);
    
            } catch (Exception e) {
                LOGGER.info("=="+e.getMessage());
            }
            return partThreadObj;
        }
    
        /**
         * 获取分块数
         * @param fileLength
         * @param partSize
         * @return
         */
        private static int calPartCount(long fileLength,long partSize) {
            int partCount = (int) (fileLength / partSize);
            if (fileLength % partSize != 0){
                partCount++;
            }
            return partCount;
        }
    
        public String getLocalFilePath() {
            return localFilePath;
        }
    
        public void setLocalFilePath(String localFilePath) {
            this.localFilePath = localFilePath;
        }
    
        public String getBucketName() {
            return bucketName;
        }
    
        public void setBucketName(String bucketName) {
            this.bucketName = bucketName;
        }
    
        public String getKey() {
            return key;
        }
    
        public void setKey(String key) {
            this.key = key;
        }
    }
    

    此处引用了多个类
    cloudStorage.basis.Constant;//定义程序中使用的变量
    cloudStorage.basis.Global;//定义了全局的静态值,错误状态值
    cloudStorage.basis.OSSClientFactory;//OSSClient工厂
    cloudStorage.oss.download.DownloadPartObj;//分块下载线程类封装
    cloudStorage.oss.download.DownloadPartThread;//分块下载线程
    cloudStorage.util.ObjectSerializableUtil;//序列工具类

    调下载方法是阻塞式,需要给调用者返回下结果,所以使用Callable和Future返回int型状态值,下面是子线程池pool中的分块下载线程DownloadPartThread的代码清单

    DownloadPartThread 代码:

    package cloudStorage.oss.download;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.io.Serializable;
    import java.util.Date;
    import java.util.concurrent.Callable;
    import org.apache.log4j.Logger;
    import cloudStorage.basis.OSSClientFactory;
    import com.aliyun.oss.common.utils.IOUtils;
    import com.aliyun.oss.model.GetObjectRequest;
    import com.aliyun.oss.model.OSSObject;
    
    /**
     * @Description: 用于上传每个part的线程类 可序列化 用于上传的断点续传
     * @author: zrk
     * @time: 2015年4月1日 上午10:35:34
     */
    public class DownloadPartThread implements Callable<DownloadPartThread>,Serializable {
    
        private static final long serialVersionUID = 1L;
        public static final Logger LOGGER = Logger.getLogger(DownloadPartThread.class);
        // 当前线程的下载开始位置
        private long startPos;
    
        // 当前线程的下载结束位置
        private long endPos;
    
        // 保存文件路径
        private String localFilePath;
    
        private String bucketName;
        private String fileKey;
        private String eTag;
        private String accessId;
        private String accessKey;
    
        public DownloadPartThread(long startPos, long endPos, String localFilePath,
                String bucketName, String fileKey, String accessId,
                String accessKey) {
            this.startPos = startPos;
            this.endPos = endPos;
            this.localFilePath = localFilePath;
            this.bucketName = bucketName;
            this.fileKey = fileKey;
            this.accessId = accessId;
            this.accessKey = accessKey;
        }
    
        @Override
        public DownloadPartThread call() {
            RandomAccessFile file = null;
            OSSObject ossObject = null;
            try {
                File pFile = new File(localFilePath);
                if(!pFile.getParentFile().exists())
                    pFile.getParentFile().mkdirs();
                file = new RandomAccessFile(localFilePath, "rw");
                //调用ossapi
                GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, fileKey);
                getObjectRequest.setRange(startPos, endPos);
                ossObject = OSSClientFactory.getInstance().getObject(getObjectRequest);
                file.seek(startPos);
                int bufSize = 1024;
                byte[] buffer = new byte[bufSize];
                int bytesRead;
                while ((bytesRead = ossObject.getObjectContent().read(buffer)) > -1) {
                    file.write(buffer, 0, bytesRead);
                    //更新开始位置,保证在出错后重下载是从上次结束的地方开始下,而不是下载整个块
                    startPos += bytesRead; 
                }
                this.eTag = ossObject.getObjectMetadata().getETag();
            } catch (Exception e) {
                LOGGER.info("=="+e.getMessage());
            } finally{
                if(ossObject!=null)IOUtils.safeClose(ossObject.getObjectContent());
                try {if(file!=null)file.close();} catch (IOException e) {e.printStackTrace();}
                return this;
            }
    
        }
    }

    每个DownloadPartThread下载线程执行结束都会将自己作为返回值返回,当前文件是否下载完整有每个线程的返回值决定。

    ObjectSerializableUtil 代码 点击查看

    DownloadPartObj 代码:

    package cloudStorage.oss.download;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    /**
     * @Description: 单个文件的下载线程集合
     * @author: zrk
     * @time: 2015年5月5日 上午10:15:11
     */
    public class DownloadPartObj implements Serializable{
        private static final long serialVersionUID = 1L;
        /**
         * 下载线程集合
         */
        List<DownloadPartThread> downloadPartThreads = Collections.synchronizedList(new ArrayList<DownloadPartThread>());
        /**
         * 下载结果
         */
        boolean result = true;
    
        public List<DownloadPartThread> getDownloadPartThreads() {
            return downloadPartThreads;
        }
        public void setDownloadPartThreads(List<DownloadPartThread> downloadPartThreads) {
            this.downloadPartThreads = downloadPartThreads;
        }
        public boolean isResult() {
            return result;
        }
        public void setResult(boolean result) {
            this.result = result;
        }
    
    }

    所有下载当前文件的线程都会操作downloadPartThreads,所以downloadPartThreads使用集合Collections.synchronizedList将其转换为一个线程安全的类。DownloadPartObj封装了downloadPartThreads和一个用于标识下载成功与失败的boolean值,定时保存序列化文件就直接序列化DownloadPartObj,DownloadPartObj的线程安全是至关重要的。

    OSSClientFactory 代码:

    package cloudStorage.basis;
    import com.aliyun.oss.OSSClient;
    public class OSSClientFactory {
        private static OSSClient ossClient = null;
        private OSSClientFactory() {
        }
        public static OSSClient getInstance() {
            if (ossClient == null) {
                // 可以使用ClientConfiguration对象设置代理服务器、最大重试次数等参数。
                // ClientConfiguration config = new ClientConfiguration();
                ossClient = new OSSClient(Constant.OSS_ENDPOINT,Constant.ACCESS_ID, Constant.ACCESS_KEY);
            }
            return ossClient;
        }
    }
    

    Constant 代码:

    package cloudStorage.basis;
    
    import cloudStorage.service.OSSConfigService;
    
    /**
     * @Description: 
     * @author: zrk
     * @time: 2015年4月1日 下午5:22:28
     */
    public class Constant {
        public static String OSS_ENDPOINT = "http://oss.aliyuncs.com/";
        public static String ACCESS_ID;
        public static String ACCESS_KEY;
        public static Integer DOWNLOAD_PART_SIZE ; // 每个下载Part的大小
        public static Integer UPLOAD_PART_SIZE ; // 每个上传Part的大小
        public static int CONCURRENT_FILE_NUMBER ; // 并发文件数。
        public static int SINGLE_FILE_CONCURRENT_THREADS ; // 单文件并发线程数。
        public static int RETRY ;//失败重试次数
        public static int SERIALIZATION_TIME;//断点保存时间间隔(秒)
        //。。。
    }
    

    Constant中数值是加载外部配置文件,也可在这儿直接配置,个别参数值断点上传时使用,只看下载的话请忽略。

    Global代码:

    package cloudStorage.basis;
    /**
     * @Description: TODO
     * @author: zrk
     * @time: 2015年4月1日 下午5:22:46
     */
    public class Global {
        public static final int SUCCESS = 1;
        public static final int ERROR = 10;
        public static final int FILE_NOT_FOUND_ERROR = 11;
        public static final int THREAD_ERROR = 12;
        public static final int NETWORK_ERROR = 13;
        public static final int OSS_SUBMIT_ERROR = 14;
    //  META
        public static final String X_OSS_META_MY_MD5 = "x-oss-meta-my-md5";
    }
    

    调用下载方式:

    实例化OSSDownloadFile后调用downloadFile方法:
    return new OSSDownloadFile(localFilePath,bucketName, key).downloadFile();

    OSS SDK文件的分块下载支持的很好,OSS官方的SDK里面也提供了一个多线程下载功能的实现,所以在实现文件的分块下载并没有什么难度。这块儿多线程下载仅供大家参考,后面自己在使用过程中继续优化。基于OSS-SDK的分块断点上传请参考OSS实现多文件多线程的断点上传(java)

    本文地址:http://blog.csdn.net/zrk1000/article/details/46286767


    展开全文
  • 多线程】——JAVA多线程文件下载

    千次阅读 2019-07-05 16:52:41
    在项目开发过程中,需要对服务器上的某些文件进行下载,最好还是多线程的,网查查阅一下资料,整理两个可以用的案例,特此记录。两个案例分别采用文件流的方式和RandomAccessFile实现。 一、文件流操作 Download...
  • 平时开发中有时会用到文件下载,为了提高文件的下载速率,采用多线程下载能够达到事半功倍的效果: packagetest; /** *文件下载类 * @author luweicheng * */ importjava.io.FileInputStream; importjava....
  • 转载文章: JAVA实现文件多线程下载,提速30倍!想学?我教你啊
  • Java多线程实现下载功能

    万次阅读 2012-11-22 11:38:19
    网上找了份资料,是别人完成的Java实现多线程下载的功能。 Java多线程的好处挺多的,可以充分利用CPU的资源,简化编程模型,简化异步事件的处理,使GUI更有效率,节约成本。 下面是实现多线程下载的代码: package ...
  • 28.java多线程实现文件下载

    千次阅读 2017-01-18 02:32:58
    多线程下载文件的思路: 1.首先获取到文件的总大小 获取文件大小的方式是通过网络读取,getContentLength()即可获取到文件的大小,使用RandomAccessFile()支持随机访问 2.根据所准备的线程数据,计算每一个线程...
  • Java实现多线程下载文件

    千次阅读 2018-01-16 18:57:00
    先使用head方法查询得到对应文件的Content-Length,然后拆分成个部分,交由线程去处理,使用"Range", "bytes=" + start + "-" + end这个header来指定下载文件的哪个部分。 2.代码实现 为了方便展示,我...
  • 原文:java多线程下载文件源码下载 源代码下载地址:http://www.zuidaima.com/share/1849085342305280.htm 多线程下载源码 ========================= java实现多线程下载, 用到了文件合并方法,该...
  • import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; imp...
  • OSS实现文件多线程的断点上传(java) 使用OSS-SDK实现文件多线程的断点上传,实现方式和断点下载使用的mainPool和pool嵌套线程池的方式相同,父线程池管理文件个数,子线程池pool每个文件的上传线程数。
  • 项目中用到分段文件下载,也使用多线程下载,提高下载效率。 自己花了时间整合成一个项目,可直接执行Junit方法看效果。
  • Java实现多线程分片文件下载

    千次阅读 2020-03-08 21:27:43
    所谓分片下载就是要利用多线程的优势,将要下载文件一块一块的分配到各个线程中去下载,这样就极大的提高了下载速度。 技术难点 并不能说是什么难点,只能说没接触过不知道罢了。 1、如何请求才能拿到数据的特定...
  • 多线程实现ftp 文件下载

    千次阅读 2018-11-27 09:39:29
    1 需求: 某个接口的纪录在ftp 服务器上,以类别/日期/时间.来存放文件,而一天可能会产生几百个文件,需要下载...3. ftp 个读取文件循环读取的时候,经常会出现,第一个文件得到字节流,而后面的文件的字节流都是null...
  • Java多线程实现多用户与服务端Socket通信

    千次阅读 多人点赞 2020-11-02 13:54:36
    Java多线程实现多用户与服务端Socket通信,类似QQ、微信、视频等客户端,多用户与服务器通信。详细记录服务端多线程的实现,目标是多用户(客户端)能够同时与服务器建立连接并通信,避免阻塞,进一步完善TCP的...
  • 下载文件的时候,一个大文件切成很多片,用多线程下载,速度会快很多 阅读代码的时候注意查看代码里面的注释 想用多线程下载文件,则, 第一:得了解 RandomAccessFile 类,这是个随机访问文件类,里面可以设置...
  • java实现多线程下载

    2015-03-09 21:09:33
    java实现多线程下载这个功能的实现由以下几部分组成: 1 建立多个线程去分别下载文件的一部分。 2 将多个线程下载文件(还在内存中),写入硬盘中的一个文件。 3 断点续传 GET /Path/FileName HTTP/1.0 Host: ...
  • Java 多线程下载技术实现

    千次阅读 2016-01-07 16:54:47
    多线程下载多线程下载技术,简单的说就是把要下载文件分成几块,由不同的线程来负责每一块数据的下载任务。技术要点 RandomAccessFile: Java中用来实现随机访问文件的类 http Range请求头 具体思路1、文件分块。...
  • java网络---实现多线程下载文件

    千次阅读 2015-10-23 21:45:22
    使用多线程下载:  1:可以记录当前下载当前的位置,实现断点下载多线程下载的时候可以记录上次下载的位置,当再次开始的时候可以帮我们记住上次下载的位置,当再次下载的时候可以从...实现多线程下载的过程可以
  • 主体类 package com.file; import com.sun.glass.ui.Size... import java.io.BufferedInputStream;...import java.io.BufferedOutputStream;...import java.io.Closeable;...import java.io.File;...import java.io.FileInpu...
  • JAVA实现多线程下载

    2013-05-26 11:24:25
    JAVA多线程下载多线程下载是为了更多的抢占服务器的资源,以达到最快的下载速度,但是,不建议开启过多线程,因为每台PC的CPU执行效率都不一样,如果开启线程较多,反而会下载的非常慢。 import java.io.File; ...
  • Java简单实现多线程复制文件

    千次阅读 2017-08-16 21:46:51
    #简单点 ...###开启多线程复制方法:线程个数,文件长度,源文件,目标文件,以参数形式传入,方法里用一个for循环去开辟新线程。 ###主方法:找到资源文件,调用开启多线程复制方法。import java.i
  • 上一篇我们说到了多线程实现文件上传,接下来继续说文件的下载 和上一篇的思路差不多,首先同样是要考虑多线程是对那一端的多线程 因为是多个客户端同时下载服务器端的文件,所以还是对服务器端的多线程 还是先...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 280,150
精华内容 112,060
关键字:

多线程实现多文件下载java

java 订阅