android多线程下载

原创 2016年08月29日 12:01:40

使用单线程下载文件会比较慢,如果使用n个线程,那么时间就会缩短为1/n,每个线程只下载其中的一段,都下载完以后再把这n段拼接起来就ok了。下面简单介绍一下多线程下载的原理和实现。


多线程下载的关键是怎样从服务器只获取文件的一部分,而不是整个文件。这里需要设置request header的一个属性:Range。

conn.setRequestProperty("Range", "bytes=" + start + "-" + end);

还有下载完毕后怎么把多个文件片段合并到一起的问题。可以使用RandomAccessFile,但要注意:每个线程需要建自己的RandomAccessFile对象,它们可以共同操作一个File,但不能使用同一个RandomAccessFile。


完整代码:

public class MainActivity extends ActionBarActivity {

    public static final String TEST_URL = "http://gdown.baidu.com/data/wisegame/e59f42264a98b05e/WeChat_861.apk";

    private TextView[] tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv1 = (TextView) findViewById(R.id.tv1);
        TextView tv2 = (TextView) findViewById(R.id.tv2);
        TextView tv3 = (TextView) findViewById(R.id.tv3);

        tv = new TextView[3];
        tv[0] = tv1;  tv[1] = tv2;  tv[2] = tv3;

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            URL url = new URL(TEST_URL);
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            conn.setRequestMethod("GET");
                            conn.setConnectTimeout(5000);
                            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");

                            String fileName = TEST_URL.substring(TEST_URL.lastIndexOf("/") + 1);
                            File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), fileName);
                            int totalLength = conn.getContentLength();
                            int subLength = totalLength / 3;

                            for(int i = 0; i < 3; i++){
                                int start = i * subLength;
                                int end = (i+1) * subLength - 1;
                                if(i == 2){
                                    end = totalLength;
                                }

                                new DownloadThread(i, start, end, file, url).start();
                            }

                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }.start();
            }
        });
    }

    class DownloadThread extends Thread{

        int threadId;
        int start;
        int end;
        File file;
        URL url;

        int currLength = 0;
        int totalLength;

        public DownloadThread(int threadId, int start, int end, File file, URL url){
            this.threadId = threadId;
            this.start = start;
            this.end = end;
            this.file = file;
            this.url = url;

            totalLength = end - start + 1;
        }

        @Override
        public void run() {
            try {
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
                conn.setRequestProperty("Range", "bytes=" + start + "-" + end);

                RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
                randomAccessFile.seek(start);

                InputStream is = conn.getInputStream();
                byte[] buf = new byte[4 * 1024];
                int len;
                while((len = is.read(buf)) != -1){
                    currLength += len;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv[threadId].setText("进程" + (threadId + 1) + " 下载进度:" + currLength + "/" + totalLength);
                        }
                    });
                    randomAccessFile.write(buf, 0, len);
                }

                is.close();
                randomAccessFile.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android之——多线程断点续传下载示例

在上一篇博文中,我们讲解了如何实现Android的多线程下载功能,通过将整个文件分成多个数据块,开启多个线程,让每个线程分别下载一个相应的数据块来实现多线程下载的功能。多线程下载中,可以将下载这个耗时...

android多线程断点下载

  • 2015-06-24 16:31
  • 76KB
  • 下载

android多线程下载

  • 2015-12-17 11:58
  • 2.97MB
  • 下载

Android底下多线程下载远程图片

点击打开链接 在某些时候我们需要在Android设备上下载远端服务器上的图片来进行显示,这里我整理出两种比较好的方法来实现远程图片的下载。 方法一、直接通过Android官方提供的...

Android多线程下载

  • 2013-10-09 16:31
  • 81KB
  • 下载

android多线程断点下载

  • 2013-11-28 15:56
  • 76KB
  • 下载

Android多线程断点续传下载文件类设计

Android多线程断点续传下载文件类设计 作者: Android开发网原创 时间: 2011-07-07    对于Android平台,很多网友可能考虑开发一个软件商店,对于Androi...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)