Thread线程系列之多线程下载

了解了这么多与线程相关的知识,那么我们也要实战一下了(在学习本篇知识之前,如果对java中的网络基础链接不太熟悉的,建议先去学一下java网络编程,再来看本文章。)

因为本篇是多线程下载的demo,所以就直接附上代码,里面都写好了注释,不影响对本篇的学习。

package com.liuqiang.Thread;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


public class DownloadFileThread {

    /**
     * 多线程下载文件
     *
     * @param args
     */

    // 定义开启线程总数 为3个线程
    private static final int threadCount = 3;

    // 下载文件的url地址
    private static final String urlFile = "http://10.135.110.63:8080/BaiduYunGuanjia.exe";

    public static void main(String[] args) {
        new Thread() {
            public void run() {
                try {
                    URL url = new URL(urlFile);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(5000);
                    int code = connection.getResponseCode();
                    if (code == 200) {

                        //(1) 获取文件总大小
                        int fileLength = connection.getContentLength();
                        System.out.println("文件总大小" + fileLength);

                        /**
                         * (2)
                         * RandomAccessFile(适用于多线程下载与上传)随机读写文件对象
                         * 在客户端创建一个与服务器端一模一样大小的文件
                         * 参数一:文件名
                         * 参数二:可读可写
                         */
                        RandomAccessFile raf = new RandomAccessFile("BaiduYunGuanjia.exe", "rw");
                        raf.setLength(fileLength);

                        //(3)计算每个线程下载的开始位置与结束位置
                        int blockSize = fileLength / threadCount; //每个线程下载(平均)的大小
                        for (int i = 0; i < threadCount; i++) {
                            int startIndex = i * blockSize; //每个线程下载的开始位置
                            int endIndex = (i + 1) * blockSize - 1; //每个线程下载的结束位置
                            //特殊情况 最后一个线程(最后一个线程可能会下载多一些)
                            if (i == threadCount - 1) {
                                //说明是最后一个线程
                                endIndex = fileLength - 1;
                            }

                            //(4)开启线程下载文件
                            DownloadThered downloadThered = new DownloadThered(startIndex, endIndex, i);
                            downloadThered.start();
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            ;
        }.start();
    }

    /**
     * 开启多线程 下载
     *
     * @author Administrator
     */
    public static class DownloadThered extends Thread {
        private int startIndex;
        private int endIndex;
        private int threadCount;

        public DownloadThered(int startIndex, int endIndex, int threadCount) {
            super();
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadCount = threadCount;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(urlFile);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(5000);
                //设置请求头 告诉服务器每个线程下载的开始位置与结束位置
                connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                int code = connection.getResponseCode();
                //200代表请求全部资源 206代表请求部分资源
                if (code == 206) {

                    /**
                     * RandomAccessFile(适用于多线程下载与上传)随机读写文件对象
                     * 在客户端创建一个与服务器端一模一样大小的文件
                     * 参数一:文件名
                     * 参数二:可读可写
                     */
                    RandomAccessFile raf = new RandomAccessFile("BaiduYunGuanjia.exe", "rw");
                    //定位 也就是设置每个线程从文件的哪个位置开始下载(设置每个线程下载的起始位置)
                    raf.seek(startIndex);

                    InputStream inStream = connection.getInputStream(); //网络获取的数据

                    //把数据写到文件当中
                    int len = -1;
                    byte[] buffer = new byte[1024];
                    while ((len = inStream.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);
                    }
                    raf.close();

                    System.out.println("线程" + threadCount + "下载完成了");

                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    }

}
 


下一篇 线程池详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值