多线程下载文件(支持暂停、取消、断点续传)----添加监听

android 单线程多任务断点排队下载(支持多界面刷新) 最近在做一个单线程多任务的断点排队下载的功能,网上确实有很多这样的demo。但是呢我发现大部分网上的demo都是很些不完整的要么就是有缺陷的,可能是我还没找到。今天我给大家带来的一个功能完整的并且可以多界面刷新,就比如:我当前界面点了下载放后台下载了,退出了当前界面在进来网上很多这样demo都没做继续更新界面。并且还做了排队。 首先我们先制定下计划:1、我们做的是断点下载,断点下载肯定是需要记录当前 阅读详情

多线程下载文件(支持暂停、取消、断点续传)

多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可。

涉及的知识及问题

  • 请求的数据如何分段
  • 分段完成后如何下载和下载完成后如何组装到一起
  • 暂停下载和继续下载的实现(wait()、notifyAll()、synchronized的使用)
  • 取消下载和断点续传的实现

一、请求的数据如何分段

首先通过HttpURLConnection请求总文件大小,而后根据线程数计算每一个线程的下载量,在分配给每一个线程去下载

fileLength = conn.getContentLength();
//根据文件大小,先创建一个空文件
//“r“——以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
//“rw“——打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
//“rws“—— 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
//“rwd“——打开以便读取和写入,对于 “rw”,还要求对文件内容的每个更新都同步写入到底层存储设备。
RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
raf.setLength(fileLength);
raf.close();
//计算各个线程下载的数据段
int blockLength = fileLength / threadCount;

二、分段完成后如何下载和下载完成后如何组装到一起

分段完成后给每一个线程的请求头设置Range参数,他允许客户端只请求文件的一部分数据,每一个线程只请求下载相应范围内的数据,使用RandomAccessFile(可随机读写的文件)写入到同一个文件里即可组装成目标文件Range,是在 HTTP/1.1里新增的一个 header field,它允许客户端实际上只请求文档的一部分(范围可以相互重叠)

Range的使用形式:

HttpUrlConnection中设置请求头

URL url = new URL(loadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
conn.setConnectTimeout(5000);
//若请求头加上Range这个参数,则返回状态码为206,而不是200
if (conn.getResponseCode() == 206) {
    InputStream is = conn.getInputStream();
    RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
    raf.seek(startPosition);//跳到指定位置开始写数据
}

三、暂停下载和继续下载的实现(wait()、notifyAll()、synchronized的使用)

关于synchronized只需记住一下五点:

  1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
  2. 然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
  3. 尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
  4. 第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
  5. 以上规则对其它对象锁同样适用.
protected void onPause() {
        if (mThreads != null)
            stateDownload = DOWNLOAD_PAUSE;
    }
    protected void onStart() {
        if (mThreads != null)
            synchronized (DOWNLOAD_PAUSE) {
                stateDownload = DOWNLOAD_ING;
                DOWNLOAD_PAUSE.notifyAll();
            }
    }

对于wait()、notify()、notifyAll()需要注意的是

  1. 调用任何对象的wait()方法时,都必须先获得该对象的锁,即调用的wait()方法必须得写在synchronized(obj){…}之内
  2. 当调用对象的wait()方法后,该线程若想继续执行,必须得再次获得该对象的锁才可以
  3. 如果A1,A2,A3线程都在obj.wait(),则B调用object.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)
  4. 当B调用object.notify/notifyAll的时候,B正持有object锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得object锁直到B退出synchronized块,释放object锁后,A1,A2,A3中的一个/全部才有机会获得锁继续执行
synchronized (DOWNLOAD_PAUSE) {
        if (stateDownload.equals(DOWNLOAD_PAUSE)) {
            DOWNLOAD_PAUSE.wait();
        }
    }

四、取消下载和断点续传的实现

取消下载即取消每个线程的执行,不建议直接使用Thread.stop()方法,安全的取消线程即run方法执行结束。只要控制住循环,就可以让run方法结束,也就是线程结束

while ((len = is.read(buffer)) != -1) {
        //是否继续下载
        if (!isGoOn)
            break;
    }

断点续传即其实和重新下载是一样的,不过文件的大小和每一个线程下载时的起始位置和结束位置都不是重新计算的。而是上次取消下载时,每一个线程保存的当前位置和结束位置,让每一个线程接着上次的地方继续下载即可

SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    //获取上次取消下载的进度,若没有则返回0
    currLength = sp.getInt(CURR_LENGTH, 0);
    for (int i = 0; i < threadCount; i++) {
        //开始位置,获取上次取消下载的进度,默认返回i*blockLength,即第i个线程开始下载的位置
        int startPosition = sp.getInt(SP_NAME + (i + 1), i * blockLength);
        //结束位置,-1是为了防止上一个线程和下一个线程重复下载衔接处数据
        int endPosition = (i + 1) * blockLength - 1;
        //将最后一个线程结束位置扩大,防止文件下载不完全,大了不影响,小了文件失效
        if ((i + 1) == threadCount)
        endPosition = endPosition * 2;
        mThreads[i] = new DownThread(i + 1, startPosition, endPosition);
        mThreads[i].start();
    }

网络获取和读写SD卡都需要添加相应权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

下面贴上全部的代码,里面有详细的注释DownLoadFile.java

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;

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

/**
 * Created by tianzhao on 2017/2/21 09:25.
 * 多线程下载文件
 */

public class DownLoadFile {


    private static final String SP_NAME = "download_file";
    private static final String CURR_LENGTH = "curr_length";
    private static final int DEFAULT_THREAD_COUNT = 4;//默认下载线程数
    //以下为线程状态
    private static final String DOWNLOAD_INIT = "1";
    private static final String DOWNLOAD_ING = "2";
    private static final String DOWNLOAD_PAUSE = "3";

    private Context mContext;

    private String loadUrl;//网络获取的url
    private String filePath;//下载到本地的path
    private int threadCount = DEFAULT_THREAD_COUNT;//下载线程数

    private int fileLength;//文件总大小
    //使用volatile防止多线程不安全
    private volatile int currLength;//当前总共下载的大小
    private volatile int runningThreadCount;//正在运行的线程数
    private Thread[] mThreads;
    private String stateDownload = DOWNLOAD_INIT;//当前线程状态

    private DownLoadListener mDownLoadListener;

    public void setOnDownLoadListener(DownLoadListener mDownLoadListener) {
        this.mDownLoadListener = mDownLoadListener;
    }

    interface DownLoadListener {
        //返回当前下载进度的百分比
        void getProgress(int progress);

        void onComplete();

        void onFailure();
    }

    public DownLoadFile(Context mContext, String loadUrl, String filePath) {
        this(mContext, loadUrl, filePath, DEFAULT_THREAD_COUNT, null);
    }

    public DownLoadFile(Context mContext, String loadUrl, String filePath, DownLoadListener mDownLoadListener) {
        this(mContext, loadUrl, filePath, DEFAULT_THREAD_COUNT, mDownLoadListener);
    }

    public DownLoadFile(Context mContext, String loadUrl, String filePath, int threadCount) {
        this(mContext, loadUrl, filePath, threadCount, null);
    }

    public DownLoadFile(Context mContext, String loadUrl, String filePath, int threadCount, DownLoadListener mDownLoadListener) {
        this.mContext = mContext;
        this.loadUrl = loadUrl;
        this.filePath = filePath;
        this.threadCount = threadCount;
        runningThreadCount = 0;
        this.mDownLoadListener = mDownLoadListener;
    }

    /**
     * 开始下载
     */
    protected void downLoad() {
        //在线程中运行,防止anr
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //初始化数据
                    if (mThreads == null)
                        mThreads = new Thread[threadCount];

                    //建立连接请求
                    URL url = new URL(loadUrl);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    int code = conn.getResponseCode();//获取返回码
                    if (code == 200) {//请求成功,根据文件大小开始分多线程下载
                        fileLength = conn.getContentLength();
                        //根据文件大小,先创建一个空文件
                        //“r“——以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
                        //“rw“——打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
                        //“rws“—— 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
                        //“rwd“——打开以便读取和写入,对于 “rw”,还要求对文件内容的每个更新都同步写入到底层存储设备。
                        RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
                        raf.setLength(fileLength);
                        raf.close();
                        //计算各个线程下载的数据段
                        int blockLength = fileLength / threadCount;

                        SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
                        //获取上次取消下载的进度,若没有则返回0
                        currLength = sp.getInt(CURR_LENGTH, 0);
                        for (int i = 0; i < threadCount; i++) {
                            //开始位置,获取上次取消下载的进度,默认返回i*blockLength,即第i个线程开始下载的位置
                            int startPosition = sp.getInt(SP_NAME + (i + 1), i * blockLength);
                            //结束位置,-1是为了防止上一个线程和下一个线程重复下载衔接处数据
                            int endPosition = (i + 1) * blockLength - 1;
                            //将最后一个线程结束位置扩大,防止文件下载不完全,大了不影响,小了文件失效
                            if ((i + 1) == threadCount)
                                endPosition = endPosition * 2;

                            mThreads[i] = new DownThread(i + 1, startPosition, endPosition);
                            mThreads[i].start();
                        }
                    } else {
                        handler.sendEmptyMessage(FAILURE);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    handler.sendEmptyMessage(FAILURE);
                }
            }
        }).start();
    }

    /**
     * 取消下载
     */
    protected void cancel() {
        if (mThreads != null) {
            //若线程处于等待状态,则while循环处于阻塞状态,无法跳出循环,必须先唤醒线程,才能执行取消任务
            if (stateDownload.equals(DOWNLOAD_PAUSE))
                onStart();
            for (Thread dt : mThreads) {
                ((DownThread) dt).cancel();
            }
        }
    }

    /**
     * 暂停下载
     */
    protected void onPause() {
        if (mThreads != null)
            stateDownload = DOWNLOAD_PAUSE;
    }

    /**
     * 继续下载
     */
    protected void onStart() {
        if (mThreads != null)
            synchronized (DOWNLOAD_PAUSE) {
                stateDownload = DOWNLOAD_ING;
                DOWNLOAD_PAUSE.notifyAll();
            }
    }

    protected void onDestroy() {
        if (mThreads != null)
            mThreads = null;
    }

    private class DownThread extends Thread {

        private boolean isGoOn = true;//是否继续下载
        private int threadId;
        private int startPosition;//开始下载点
        private int endPosition;//结束下载点
        private int currPosition;//当前线程的下载进度

        private DownThread(int threadId, int startPosition, int endPosition) {
            this.threadId = threadId;
            this.startPosition = startPosition;
            currPosition = startPosition;
            this.endPosition = endPosition;
            runningThreadCount++;
        }

        @Override
        public void run() {
            SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
            try {
                URL url = new URL(loadUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
                conn.setConnectTimeout(5000);
                //若请求头加上Range这个参数,则返回状态码为206,而不是200
                if (conn.getResponseCode() == 206) {
                    InputStream is = conn.getInputStream();
                    RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
                    raf.seek(startPosition);//跳到指定位置开始写数据
                    int len;
                    byte[] buffer = new byte[1024];
                    while ((len = is.read(buffer)) != -1) {
                        //是否继续下载
                        if (!isGoOn)
                            break;
                        //回调当前进度
                        if (mDownLoadListener != null) {
                            currLength += len;
                            int progress = (int) ((float) currLength / (float) fileLength * 100);
                            handler.sendEmptyMessage(progress);
                        }

                        raf.write(buffer, 0, len);
                        //写完后将当前指针后移,为取消下载时保存当前进度做准备
                        currPosition += len;
                        synchronized (DOWNLOAD_PAUSE) {
                            if (stateDownload.equals(DOWNLOAD_PAUSE)) {
                                DOWNLOAD_PAUSE.wait();
                            }
                        }
                    }
                    is.close();
                    raf.close();
                    //线程计数器-1
                    runningThreadCount--;
                    //若取消下载,则直接返回
                    if (!isGoOn) {
                        //此处采用SharedPreferences保存每个线程的当前进度,和三个线程的总下载进度
                        if (currPosition < endPosition) {
                            sp.edit().putInt(SP_NAME + threadId, currPosition).apply();
                            sp.edit().putInt(CURR_LENGTH, currLength).apply();
                        }
                        return;
                    }
                    if (runningThreadCount == 0) {
                        sp.edit().clear().apply();
                        handler.sendEmptyMessage(SUCCESS);
                        handler.sendEmptyMessage(100);
                        mThreads = null;
                    }
                } else {
                    sp.edit().clear().apply();
                    handler.sendEmptyMessage(FAILURE);
                }
            } catch (Exception e) {
                sp.edit().clear().apply();
                e.printStackTrace();
                handler.sendEmptyMessage(FAILURE);
            }
        }

        public void cancel() {
            isGoOn = false;
        }
    }

    private final int SUCCESS = 0x00000101;
    private final int FAILURE = 0x00000102;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            if (mDownLoadListener != null) {
                if (msg.what == SUCCESS) {
                    mDownLoadListener.onComplete();
                } else if (msg.what == FAILURE) {

                    mDownLoadListener.onFailure();
                } else {
                    mDownLoadListener.getProgress(msg.what);
                }
            }
        }
    };
}

在MainActivity中的使用

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    DownLoadFile downLoadFile;
    private String loadUrl = "http://gdown.baidu.com/data/wisegame/d2fbbc8e64990454/wangyiyunyinle_87.apk";
    private String filePath = Environment.getExternalStorageDirectory()+"/"+"网易云音乐.apk";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tvprogress = (TextView) findViewById(R.id.tv_progress);
        downLoadFile = new DownLoadFile(this,loadUrl, filePath, 3);
        downLoadFile.setOnDownLoadListener(new DownLoadFile.DownLoadListener() {
            @Override
            public void getProgress(int progress) {
                tvprogress.setText("当前进度 :"+progress+" %");
            }

            @Override
            public void onComplete() {
                Toast.makeText(MainActivity.this,"下载完成",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure() {
                Toast.makeText(MainActivity.this,"下载失败",Toast.LENGTH_SHORT).show();
            }
        });
        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                downLoadFile.downLoad();
            }
        });
        findViewById(R.id.bt_pause).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                downLoadFile.onPause();
            }
        });
        findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                downLoadFile.onStart();
            }
        });
        findViewById(R.id.bt_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                downLoadFile.cancel();
            }
        });
    }

    @Override
    protected void onDestroy() {
        downLoadFile.onDestroy();
        super.onDestroy();
    }
}

文章来源:https://blog.youkuaiyun.com/tianzhaoai/article/details/56673071

详解java线程的开始、暂停、继续 本文将介绍通过线程读取文件内容,并且可以控制线程的开始、暂停、继续,来控制读文件。具有一定的参考作用,下面跟着小编一起来看下吧 立即下载

相关推荐

别再手动算LLC了!用Mathcad 15分钟搞定谐振参数与增益曲线(附已验证产品案例)

本文详细介绍了如何利用Mathcad在15分钟内高效完成LLC谐振变换器的参数计算与增益曲线绘制。通过对比传统工具,突出Mathcad在自然数学表达、实时单位换算和动态参数关联方面的独特优势,帮助电源工程师大幅提升设计效率。文章还提供了已验证的产品案例和实用模板,助力工程师快速掌握谐振参数优化技巧。

weixin_42548888的博客 548

多线程下载

多线程下载 使用多线程下载文件可以很快地完成文件的下载,比如迅雷就是采用了多线程的方式来实现快速下载的。之所以采用多线程的形式会加快下载速度,是因为客户端启动多个线程进行下载时服务器就会为该客户端提供相应的服务,自然客户端就拥有了较快的下载速度。实际上并不是客户端并发的下载线程越多,程序下载速度就越快,,因为当客户端开启太多的并发线程之后,应用程序需要维护每条线程的开销,线程同步的开销,这些开销反...

哈 3505

从零到一:如何用YOLOv8和PyQt5打造你的第一个花卉识别桌面应用

本文详细介绍了如何使用YOLOv8和PyQt5从零开始构建一个花卉识别桌面应用。涵盖环境搭建、数据准备、模型训练、界面设计、模型集成与性能优化等全流程,帮助开发者快速掌握深度学习目标识别技术的实际应用。

weixin_29048775的博客 454

多线程下载文件(支持暂停、取消、断点续传)

多线程下载文件(支持暂停、取消、断点续传)多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可。涉及的知识及问题 请求的数据如何分段 分段完成后如何下载和下载完成后如何组装到一起 暂停下载和继续下载的实现(wait()、notifyAll()、synchronize

xyTianZhao 1万+

从0到1:.NET 9 OpenAPI全攻略!Swagger vs Scalar UI谁更强?

OpenAPI:.NET 9的智能文档革命 本文深入解析.NET 9的OpenAPI支持,对比Swagger UI与Scalar UI的优劣,提供实战代码示例: 一键生成:AddOpenApi()+MapOpenApi()快速生成标准文档 UI工具对决: Swagger UI功能全面但复杂 Scalar UI简约现代,原生支持cURL/HTTPie 进阶技巧: XML注释增强文档可读性 自定义Transformer实现文档动态修改 🔥核心价值:.NET 9的OpenAPI方案显著降低API文档维护成本,开

java专栏 1428

Python爬虫实战:5分钟抓取东方财富股票数据并保存为CSV

在投资分析与量化研究的日常工作中,获取结构化、可用的金融数据往往是第一步。对于个人投资者和量化入门者而言,如何高效获取A股全市场行情,常常面临网页动态加载、反爬机制与数据整理繁琐等挑战。本文从数据采集的基础概念出发,介绍如何利用Python这一通用编程语言,通过requests库请求财经网站公开的HTTP接口,获取返回的JSON数据,再借助pandas进行字段映射、数据清洗与表格化处理。这种方式相比传统页面解析具有响应快、结构稳定、易于批量操作的显著优势,尤其适合构建个人股票数据池、验证选股策略或进行市场情

weixin_33146151的博客 251

【Golang】多线程下载器的实现

多线程下载,顾名思义就是对一个文件进行切片访问,等待所有的文件下载完成后在本地进行拼接成一个整体文件的过程。因此可以利用 golang 的多协程对每个分片同步下载,之后再合并且进行md5校验或者总长度校验。

luyoung0001@gmail.com的博客 1945

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

a_zxswer的博客 191

如何开启Chrome和Edge的多线程下载功能(Parallel downloading)

众所周知,当我们想要在网上下载一个东西时那下载速度简直比我奶奶走路还要慢。许多朋友为了加快下载速度会喜欢去用IDM这种工具。但是,有一种更简便的方法:那就是开启浏览器的多线程下载,之后你会被那感人的速度给经惊艳到。

weixin_66899911的博客 8万+

MATLAB之把多个小cell拼成一个数组

问题描述 现有一个cell向量 L (90000,1),每个元素都是由一个(100X9)的double数组组成的.如图. 其中, 每个cell元素都是一个单独的数据, 我们要把它转换成(90000, 19, 100)的三维数组. cell2mat, 但是所有的数据会堆叠起来 L2=cell2mat(L); % (90000, 19) reshape, 变成三维数组 reshape的原理是从上到下, 从左往右拆开重组. 目前只有19这一维数据与要求一致, 那就以这个为突破口. L2=L2'; %

落日之城 9250

在 SAP 里,想让“同一笔业务”在多个账套(平行分类账)中生成不同编号的会计凭证,标准做法就是

摘要:SAP系统中实现同一业务在不同分类账生成独立凭证号的方法是为每个分类账配置独立的凭证类型-编号范围映射。通过FBN1/OBA7等事务码为各分类账分配专属编号段,系统过账时会按分类账自动取号,确保凭证号互不冲突。该方案适用于S/4HANA和ECC系统,支持标准过账(F-02)或分类账专属过账(FB01L)两种模式,最终实现"一业务多账套,各自独立编号"的目标。

金牌架构师 550

Android多任务并行下载、断点续传

这个开源库叫 Aria,是我在搞断点续传时发现的,仔细了解后发现,真香!!! 它是一个简单易用,稳当高效的下载框架,不仅可以断点续传,还支持多任务自动调度,它更加灵活的事件监听器,让你能更容易的监听暂停、恢复、完成、失败、取消下载等状态。 开源库地址是:https://github.com/AriaLyy/Aria 目前已经有3.2k star,Aria有以下特点: 简单、方便 可以在Acti...

程序员大佬超的博客 3212

【33】软考软件设计师——算法题(二):贪心法与回溯法深度精讲|第4题进阶满分攻略

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏第33篇,承接第32篇分治法与动态规划,聚焦**下午第4题算法大题进阶核心**,详解贪心法与回溯法两大高频难点算法。全文超4000字深度拆解贪心法核心原理、贪心选择性质、局部最优推全局最优的底层逻辑,厘清贪心算法适用边界与经典误区;深挖回溯法深度优先遍历思想、递归回溯三步流程、可行性剪枝与最优性剪枝两大核心技巧;全覆盖活动选择、零钱兑换、01背包贪心禁区、八皇后、全排列等软考必考经典题型;配套标准化算法框架代码、考场填空模板、剪枝优化实操案例

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 440

android同时下载多个文件,android学习-多文件下载以及断点续传

首先先感谢丰神,本文源于他的这篇微博http://blog.youkuaiyun.com/cfy137000/article/details/54838608,思路很棒,然后自己跟着代码撸了一遍,然后为了加深理解就上传到博客上来。首先说下主要都到了什么开发技术吧,网络请求是使用okhttp,然后涉及多线程的部分是使用rxjava,之前自己只是简单的看了一下rxjava,然后实际运用了下,感觉熟悉了很多;然后还...

weixin_35223524的博客 1376

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

android学习-多文件下载以及断点续传

首先先感谢丰神,本文源于他的这篇微博http://blog.youkuaiyun.com/cfy137000/article/details/54838608,思路很棒,然后自己跟着代码撸了一遍,然后为了加深理解就上传到博客上来。 首先说下主要都到了什么开发技术吧,网络请求是使用okhttp,然后涉及多线程的部分是使用rxjava,之前自己只是简单的看了一下rxjava,然后实际运用了下,感觉熟悉了很多;然后

thankYouLikeMe的博客 1230

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

iOS 大文件下载、断点续传、后台下载 —— HERO博客

本篇简述一下实现文件下载功能,包含大文件下载,后台下载,杀死进程,重新启动时继续下载,设置下载并发数,监听网络改变等,并在最后附有Demo。 下载功能的实现: 使用的网络连接的类为NSURLSession。该类用以替代NSURLConnection,在iOS7时推出,至此iOS系统才有了后台传输。在初始化NSURLSession前,需要先创建NSURLSessionConfiguration,可以理解为是NSURLSession需要的一个配置。NSURLSessionConfiguration有三.

学习一定要有针对性的练习-实操! 1046

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

android下载封装类Download,支持断点下载

各种回调, 支持断点下载 public class Download implements Serializable { private static final int START = 1; // 开始下载 private static final int PUBLISH = 2; // 更新进度 p

gundumw100的专栏 584

断点续传-----下载视频

创建一个工具类————添加方法 package com.example.mr.combwiezhaoweibo1510a20180119; import android.content.Context; import android.content.SharedPreferences; import android.os.Handler; import android.os.Message

Mrzhaoplus的博客 773

ThinDownloadManager实战教程:构建带进度监听的多线程下载应用

想要在Android应用中实现高效的文件下载功能吗?ThinDownloadManager正是你需要的终极解决方案!这款强大的Android下载库专为开发者设计,让你轻松构建带进度监听的多线程下载应用,同时避免使用Android系统DownloadManager的繁琐权限问题。😊 ## 为什么选择ThinDownloadManager? ThinDownloadManager是一个轻量级的A

gitblog_00345的博客 420

多线程下载 断点续传

//依赖 compile 'com.squareup.okhttp3:okhttp:3.6.0' compile 'com.squareup.okio:okio:1.11.0' //权限 //main.xml <LinearLayout xmlns:android="http

Adefacuse的博客 391

android 多线程异步下载文件,造轮子之 Android 多线程多任务断点续传下载器(设计篇)...

前段时间面试,被问到 app 的自动更新是怎么做的,文件下载怎么实现的?用了多线程吗?是否支持断点续传?一下蒙逼,因为直接用第三方框架实现的文件下载,这些问题完全没想过。回来后觉得这里面其实涉及很多知识点,就打算自己动手封装一个支持多线程多任务断点续传的库,用了一个星期的业余时间,目前主要功能基本完成,所以记录一下这个过程中遇到的问题和收获1. 涉及知识点听起来并不复杂的一个功能,但是实际动手做起...

weixin_33835122的博客 435

鸿蒙开发实战:5分钟搞定网络文件下载(含进度条显示与断点续传技巧)

本文详细介绍了在鸿蒙系统中实现高效文件下载的实战技巧,包括基础下载功能、进度条显示和断点续传等高级功能。通过代码示例和优化建议,帮助开发者快速掌握网络资源文件的下载与管理,提升应用用户体验。

weixin_29224309的博客 273

Android 多线程断点下载

QDownload QDownload是基于Android平台实现的下载框架。API简洁易上手,只需5分钟即可实现一个多任务、多线程、断点下载的功能 支持功能如下: 支持多个下载任务同时下载 单个任务支持开多个线程下载 支持断点下载,在断网、进程被划掉可恢复下载 自动校验服务器文件服务器是否支持断点下载,如果不支持则会开启单线程任务下载 支持应用全局监听下载进度回调 支持下载速度显示 支持添加下载任务,暂停下载,恢复下载,取消下载 支持批量暂停,批量恢复下载 先贴个效果图 主页 多任务多线程断点下载页

越努力越幸运 3347

android 多线程分段下载,GitHub - wpan1993/Okhttp-Multiple-Thread-Download-Demo: Android Okhttp多线程断点续传下载Demo...

Okhttp-Multiple-Thread-Download-DemoAndroid Okhttp多线程断点续传下载Demo最近项目需要使用到断点下载功能,笔者比较喜欢折腾,想方设法抛弃SharedPreferences,尤其是sqlite作记录辅助,改用临时记录文件的形式记录下载进度,本文以断点下载为例。先看看demo运行效果图:断点续传:记录上次上传(下载)节点位置,下次接着该位置继续上传(...

weixin_39608509的博客 367

Fetch在游戏应用中的应用:大文件下载与资源管理的终极方案

Fetch作为Android平台上最优秀的文件下载库,为游戏应用的大文件下载与资源管理提供了完整解决方案。无论是大型游戏安装包、高清纹理资源还是更新补丁,Fetch都能确保稳定、高效的下载体验,帮助开发者提升用户留存率和满意度。 ## 为什么游戏应用需要专业的下载解决方案? 现代移动游戏的资源包体积越来越大,动辄数GB的安装包和频繁的更新补丁对下载功能提出了极高要求。普通的下载方式往往面临**

gitblog_00857的博客 837

Unity大文件下载:基于UnityWebRequest实现高效断点续传方案

在Unity开发中,大文件下载是资源热更新、AssetBundle加载等场景的常见需求。HTTP协议的Range请求头是实现断点续传的核心原理,它允许客户端指定下载文件的字节范围,服务器返回206 Partial Content响应,从而实现从中断处继续下载的技术。这种机制对于提升用户体验、节省流量和时间具有重要价值,尤其适用于移动端游戏更新、高清资源包下载等应用场景。本文聚焦于UnityWebRequest的自定义DownloadHandlerScript实现,通过精细控制数据流和文件写入模式,解决了原生

weixin_30254435的博客 357
上一篇: 关于Android Activity之间传递数据的6种方式
下一篇: Android刘海屏适配
augfun
博客等级 码龄10年 311粉丝 662原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值