Java 仿迅雷多线程下载

简介: package net.webjoy.jackluo.android_json; /** * 1.http Range "bytes="+ start+end * 2.RandomAccessFile设置写入的位置 * 3开启多线程下载 * * Created by jackluo on 9/30/15.
package net.webjoy.jackluo.android_json;

/**
 *  1.http Range "bytes="+  start+end
 *  2.RandomAccessFile设置写入的位置
 *  3开启多线程下载
 *
 * Created by jackluo on 9/30/15.
 */

import android.os.Environment;
import android.os.Handler;
import android.os.Message;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 多线程下载
 */
public class DownLoad {
    //创建一个线程池      创建三个线程
    private Executor threadPool = Executors.newFixedThreadPool(3);

    private Handler handler;

    public DownLoad(Handler handler){
        this.handler = handler;
    }

    //创建一个线程池对象
    static class DownLoadRunnable implements Runnable{

        private String url;
        private String fileName;
        private long start ;//开始位置
        private long end;//结束位置
        private Handler handler;
        public DownLoadRunnable(String url,String fileName,long start,long end,Handler handler){
            this.url = url;
            this.fileName = fileName;
            this.start = start;
            this.end = end;
            this.handler = handler;
        }

        @Override
        public void run() {

            try {
                URL httpUrl = new URL(url);
                HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();
                connection.setRequestMethod("GET");
                connection.setReadTimeout(5000);
                //设置下载位置  向服务器拿到指定的流信息
                connection.setRequestProperty("Range", "bytes=" + start + "-" + end);
                //创建一个文件  根据指定位置写入信息
                RandomAccessFile accessFile = new RandomAccessFile(new File(fileName),"rwx");
                accessFile.seek(start);//设置读写的位置
                InputStream inputStream = connection.getInputStream();
                byte[] b = new byte[1024*4];//设置缓冲区的大小存
                int len=0;
                while ((len = inputStream.read(b))!=-1){
                    accessFile.write(b,0,len);
                }
                if (accessFile !=null){
                    accessFile.close();
                }
                if (inputStream !=null){
                    inputStream.close();
                }
                //给主线程发送一个消息
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);

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


        }
    }

    public void downLoadFile(String url){
        try {
            URL httpUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.setReadTimeout(5000);
            int count = connection.getContentLength();//获取了图片的大小
            int block = count/3;


            //算线程的启始位置
            String fileName = getFileName(url);
            File parent = Environment.getExternalStorageDirectory();
            File fileDownLoad = new File(parent,fileName);
            /**
             * 11 / 3 = 每个下载 3个字节3 还余出2个字节空间
             * 第一个线程 0-2
             * 第二个线程 3-5
             * 第三个线程 6-10
             *
             *
             */
            for (int i=0;i<3;i++){
                long start = i*block;
                long end = (i+1)*block -1;
                if (i==2){
                    end = count;
                }
                DownLoadRunnable runnable = new DownLoadRunnable(url, fileDownLoad.getAbsolutePath(),start,end,handler);
                //提交任务
                threadPool.execute(runnable);
            }



        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取 URL后缀名
     */
    public String getFileName(String url){
        return url.substring(url.lastIndexOf("/")+1);
    }

}
package net.webjoy.jackluo.android_json;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class DownLoadActivity extends AppCompatActivity {

    private Button button;
    private TextView textView;
    private int count =1;
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            //super.handleMessage(msg);
            int result = msg.what;
            count +=result;
            if (count==3){
                textView.setText("download success");
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);

        button = (Button) findViewById(R.id.downlad_btn);
        textView = (TextView) findViewById(R.id.textView);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new Thread(){
                    @Override
                    public void run() {
                        DownLoad load = new DownLoad(handler);
                        load.downLoadFile("http://news.jsyks.com/photo/img1a.xgo-img.com.cn/pics/737/736406.jpg");
                    }
                }.start();



            }
        });
    }


}

 

目录
相关文章
|
6天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
12 4
|
1天前
|
消息中间件 供应链 Java
掌握Java多线程编程的艺术
【10月更文挑战第29天】 在当今软件开发领域,多线程编程已成为提升应用性能和响应速度的关键手段之一。本文旨在深入探讨Java多线程编程的核心技术、常见问题以及最佳实践,通过实际案例分析,帮助读者理解并掌握如何在Java应用中高效地使用多线程。不同于常规的技术总结,本文将结合作者多年的实践经验,以故事化的方式讲述多线程编程的魅力与挑战,旨在为读者提供一种全新的学习视角。
19 3
|
2天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
12 1
|
6天前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
16 4
|
6天前
|
缓存 Java 调度
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文旨在为读者提供一个关于Java多线程编程的全面指南。我们将从多线程的基本概念开始,逐步深入到Java中实现多线程的方法,包括继承Thread类、实现Runnable接口以及使用Executor框架。此外,我们还将探讨多线程编程中的常见问题和最佳实践,帮助读者在实际项目中更好地应用多线程技术。
15 3
|
6天前
|
缓存 安全 Java
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文将深入探讨Java中的多线程编程,包括其基本原理、实现方式以及常见问题。我们将从简单的线程创建开始,逐步深入了解线程的生命周期、同步机制、并发工具类等高级主题。通过实际案例和代码示例,帮助读者掌握多线程编程的核心概念和技术,提高程序的性能和可靠性。
10 2
|
7天前
|
Java
Java中的多线程编程:从基础到实践
本文深入探讨Java多线程编程,首先介绍多线程的基本概念和重要性,接着详细讲解如何在Java中创建和管理线程,最后通过实例演示多线程的实际应用。文章旨在帮助读者理解多线程的核心原理,掌握基本的多线程操作,并能够在实际项目中灵活运用多线程技术。
|
27天前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
38 1
C++ 多线程之初识多线程
|
11天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
12 3