• Java实现多线程下载


    思路:

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

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

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

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

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

     首先,我们要先写一个方法,方法的参数包含URL地址,保存的文件地址,切割后的文件开始位置和结束位置,这样我们就能把分段文件下载到本地。并且这个方法要是run方法,这样我们启动线程时就直接执行该方法。

    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;
            }
    
        }

     然后我们创建线程池,线程池的长度可以自定义,然后循环创建线程来执行请求,每条线程的请求开始位置和结束位置都不同,本地存储的文件开始位置和请求开始位置相同,这样就可以实现多线程下载了。

    public class DownloadFileWithThreadPool
    {
        public void getFileWithThreadPool(String urlLocation,String filePath, int poolLength) throws IOException
        {
            Executor threadPool = Executors.newFixedThreadPool(poolLength);
            
            long len = getContentLength(urlLocation);
            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);
            }
        }
    
        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;
        }
  • 相关阅读:
    server2012/win8 卸载.net framework 4.5后 无法进入系统桌面故障解决【转】
    Entity Framework中AutoDetectChangesEnabled為false時更新DB方法
    git常用命令备忘录
    MSSQL日誌傳輸熱備份注意事項
    c#生成唯一编号方法记录,可用数据库主键 唯一+有序
    Angular 隨記
    使用dumpbin命令查看dll导出函数及重定向输出到文件【轉】
    UML类图与类的关系详解【转】
    知識隨記
    session不会过期
  • 原文地址:https://www.cnblogs.com/iwideal/p/6045118.html
Copyright © 2020-2023  润新知