android使用http协议实现多线程断点下载

关于多线程:

如果你通过多个线程同时与服务器连接,那么你就可以榨取到较高的带宽了。例如原来有10个用户都通过单一线程服务器相连,服务器的总带宽假设为56Kbps,则每个用户(每个线程)分到的带宽是5.6Kbps,即0.7K字节/秒。如果你同时打开两个线程与服务器连接,那么共有11个线程与服务器连接,而你获得的带宽将是56/11*2=10.2Kbps,约1.27K字节/秒,将近原来的两倍。你同时打开的线程越多,你所获取的带宽就越大(原来是这样,以后每次我都通过1K个线程连接:P)。当然,这种情况下占用的机器资源也越多。有些号称“疯狂下载”的下载工具甚至可以同时打开100个线程连接服务器。ps:摘自百度百科

package com.example.test_download;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Environment;
import android.widget.Toast;

/*path:下载路径
 * fillName:文件名
 *
 *
 * */
public class downLoader {
    private static int threadcount = 3;// 开启线程数
    private static long blocksize;// 每个线程下载的大小
    private static int Runningthreadcount;// 用来记录存活线程

    public downLoader(final String path, final String fileName)
            throws IOException {
        new Thread(new Runnable() {

            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(path);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(10000);
                    connection.connect();
                } catch (Exception e) {
                    
                    System.out.println("网络连接失败");
                }
                try {
                    if (connection.getResponseCode() == 200) {
                        long size = connection.getContentLength();//得到文件大小
                        System.out.println(size);
                        blocksize = size / threadcount;//blocksize为平均线程下载大小,threadcount默认为3
                        File file = new File(Environment
                                .getExternalStorageDirectory(), fileName);
                        /*
                         * 当使用Buffreader像磁盘写入数据时。当磁盘缓冲区未满时不会向里面写数据,所以用RandomAccessFill
                         * 实时写入,
                         * */
                        RandomAccessFile raf = new RandomAccessFile(file, "rw");
                        raf.setLength(size);
                        Runningthreadcount = threadcount;
                        for (int i = 0; i < threadcount; i++) {
                            long startIndex = i * blocksize;//开始位置
                            long endIndex = (i + 1) * blocksize;//结束位置
                            if (i == threadcount - 1) {
                                endIndex = size - 1;
                            }
                            //开启线程下载
                            new DownLoadThread(i, startIndex, path, endIndex,
                                    fileName).start();
                        }

                    }
                } catch (FileNotFoundException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
                connection.disconnect();

            }
        }).start();

    }

    private static class DownLoadThread extends Thread {

        private int threadId;
        private long statrIndex;
        private String path;
        private long endIndex;
        private String fileName;

        public DownLoadThread(int threadId, long statrIndex, String path,
                long endIndex, String fileName) {
            super();
            this.threadId = threadId;
            this.statrIndex = statrIndex;
            this.path = path;
            this.endIndex = endIndex;
            this.fileName = fileName;
        }

        public void run() {
            try {

                int total = 0;// 当前线程下载 大小
                //把下载的了大小写入日志文件
                File position = new File(
                        Environment.getExternalStorageDirectory(), threadId
                                + ".log");// 日志文件
                URL url = new URL(path);
                HttpURLConnection connection = (HttpURLConnection) url
                        .openConnection();
                connection.setRequestMethod("GET");
                //判断日志文件是否存在,得到下载大小
                if (position.exists() && position.length() > 0) {
                    FileInputStream fis = new FileInputStream(position);
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(fis));
                    String lasttotalstr = br.readLine();
                    int lasttotal = Integer.valueOf(lasttotalstr);
                    System.out.println(threadId + "  " + lasttotal);
                    statrIndex += lasttotal;
                    total += lasttotal;
                    fis.close();
                    br.close();
                }
                //从得到的断点继续下载
                connection.setRequestProperty("Range", "bytes=" + statrIndex
                        + "-" + endIndex);
                connection.setConnectTimeout(10000);
                connection.connect();
                int code = connection.getResponseCode();
                System.out.println(code);
                InputStream stream = connection.getInputStream();
                File file = new File(Environment.getExternalStorageDirectory(),
                        fileName);
                RandomAccessFile raf = new RandomAccessFile(file, "rw");
                raf.seek(statrIndex);
                System.out.println(threadId + "线程写入地址" + statrIndex);
                int len = 0;
                byte[] buff = new byte[1024 * 1024];

                while ((len = stream.read(buff)) != -1) {
                    RandomAccessFile rf = new RandomAccessFile(position, "rwd");
                    raf.write(buff, 0, len);
                    total += len;
                    rf.write(String.valueOf(total).getBytes());
                    rf.close();

                }
                stream.close();
                raf.close();
                System.out.println("end" + "wan" + threadId);

            } catch (Exception e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            } finally {
                //处理线程安全问题
                synchronized (downLoader.class) {
                    System.out.println("线程" + threadId + "下载完了");
                    Runningthreadcount = Runningthreadcount - 1;
                    System.out.println("Runningthreadcount"
                            + Runningthreadcount);
                    System.out.println("下载完毕");
                    if (Runningthreadcount < 1) {
                        System.out.println("下载完毕");
                        for (int i = 0; i < threadcount; i++) {
                            File files = new File(
                                    Environment.getExternalStorageDirectory(),
                                    i + ".log");
                            files.delete();//下载完成后删除日志文件

                        }
                    }
                }
            }
        }

    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值