安卓 线程池的正确使用 模仿电影下载

d0b29780c49cff8d0f326ec06124e3c4

---介绍---

但凡有点开发经验的同学都知道,频繁的创建和销毁线程是会给系统带来比较大的性能开销的。所以线程池就营运而生了。那么使用线程池有什么好处呢?

  • 降低资源消耗
    可以重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 提高响应速度
    当任务到达时,任务可以不需要等到线程创建就能立即执行。
  • 提高线程的可管理性
    线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

线程池的运行策略原理

1、 接口继承关系

线程池所涉及到的接口和类并不是很多,其继承体系也相对简单。相关继承关系如图:

线程池接口关系图

最顶层的接口Executor仅声明了一个方法execute。ExecutorService 接口在其父接口基础上,声明了包含但不限于shutdown、shutdownNow、submit、invokeAll等方法。ScheduledExecutorService接口,则是声明了一些和定时任务相关的方法:schedule、scheduleAtFixedRate等。线程池的核心实现是在ThreadPoolExecutor类中,我们使用Executors调用newFixedThreadPool、newSingleThreadExecutor和newCachedThreadPool等方法创建线程池均是ThreadPoolExecutor类型。

我们看看的构造函数:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    }

核心参数分析:

参数说明
corePoolSize核心线程数。当线程数小于该值时,线程池会优先创建新线程来执行新任务
maximumPoolSize线程池所能维护的最大线程数
keepAliveTime空闲线程的存活时间
unit参数keepAliveTime空闲线程的存活时间的单位 这是一个枚举类
workQueue任务队列,用于缓存未执行的任务
threadFactory线程工厂。可通过工厂为新建的线程设置更有意义的名字
handler拒绝策略。当线程池和任务队列均处于饱和状态时,使用拒绝策略处理新任务。默认是 AbortPolicy,即直接抛出异常

2、 线程创建规则策略

对于线程池的创建,线程池所能创建的线程数量受限于corePoolSize和maximumPoolSize两个参数值。线程的创建时机则和corePoolSize以及workQueue 两个参数有关。

下面列举一下线程创建的几个规则(线程池中无空闲线程),如下:

线程情况策略
线程数量小于 corePoolSize直接创建新线程处理新的任务
线程数量大于等于 corePoolSize,workQueue 未满则缓存新任务
线程数量大于等于 corePoolSize,但小于 maximumPoolSize,且 workQueue 已满则创建新线程处理新任务
线程数量大于等于 maximumPoolSize,且 workQueue 已满则使用拒绝策略处理新任务

简化一下上面的规则:

序号条件动作
1线程数 < corePoolSize创建新线程
2线程数 ≥ corePoolSize,且 workQueue 未满缓存新任务
3corePoolSize ≤ 线程数 < maximumPoolSize,且 workQueue 已满创建新线程
4线程数 ≥ maximumPoolSize,且 workQueue 已满使用拒绝策略处理

《Android开发艺术探索》一书中建议:

a. 核心线程数等于CPU核心数+1;
b. 线程池的最大线程数等于CPU的核心数的2倍+1;
c. 核心线程无超时机制,分核心线程的闲置时间为4秒;
d. 任务队列的容量为128.

3、 线程资源回收策略

考虑到系统资源是有限的,对于线程池超出 corePoolSize 数量的空闲线程应进行回收操作。进行此操作存在一个问题,即回收时机。目前的实现方式是当线程空闲时间超过 keepAliveTime 后,进行回收。除了核心线程数之外的线程可以进行回收,核心线程内的空闲线程也可以进行回收。回收的前提是allowCoreThreadTimeOut属性被设置为 true,通过public void allowCoreThreadTimeOut(boolean) 方法可以设置属性值。

4、 排队策略

如上面线程创建规则所说的,当线程数量大于等于corePoolSize,workQueue未满时,则缓存新任务。这里要考虑使用什么类型的容器缓存新任务,通过 JDK 文档介绍,我们可知道有3种类型的容器可供使用,分别是同步队列,有界队列和无界队列。对于有优先级的任务,这里还可以增加优先级队列。以上所介绍的4种类型的队列,对应的实现类如下:

实现类类型说明
SynchronousQueue同步队列该队列不存储元素,每个插入操作必须等待另一个线程调用移除操作,否则插入操作会一直阻塞
ArrayBlockingQueue有界队列基于数组的阻塞队列,按照 FIFO 原则对元素进行排序
LinkedBlockingQueue无界队列基于链表的阻塞队列,按照 FIFO 原则对元素进行排序
PriorityBlockingQueue优先级队列具有优先级的阻塞队列

5、 拒绝策略

如上线程创建规则策略中所说,当线程数量大于等于 maximumPoolSize,且 workQueue 已满,或者是当前线程池被关闭了则使用拒绝策略处理新任务。Java 线程池提供了4种拒绝策略实现类, 如下:

实现类说明
AbortPolicy丢弃新任务,并抛出 RejectedExecutionException
DiscardPolicy不做任何操作,直接丢弃新任务
DiscardOldestPolicy丢弃队列列首的元素,并执行新任务
CallerRunsPolicy会在线程池当前正在运行的Thread线程池中处理被拒绝的任务

以上4个拒绝策略中,AbortPolicy 是线程池实现类所使用的默认策略。我们也可以通过方法:

public void setRejectedExecutionHandler(RejectedExecutionHandler handler)

修改线程池的拒绝策略。

6、 线程池中的线程是如何创建的

在线程池的实现上,线程的创建是通过线程工厂接口ThreadFactory的实现类来完成的。默认情况下,线程池使用Executors.defaultThreadFactory()方法返回的线程工厂实现类。当然,我们也可以通过方法:

public void setThreadFactory(ThreadFactory threadFactory)

进行动态修改线程的创建。具体细节可以参考具体细节可以参考Executors.defaultThreadFactory()的实现。

7、 线程池的线程是如何实现复用的

在线程池中,线程的复用是线程池的关键所在。这就要求线程在执行完一个任务后,不能立即退出。对应到具体实现上,工作线程在执行完一个任务后,会再次到任务队列获取新的任务。如果任务队列中没有任务,且 keepAliveTime 也未被设置,工作线程则会被一致阻塞下去。通过这种方式即可实现线程复用。

说完原理,再来看看线程的创建和复用的相关代码(基于 JDK 1.8),如下:

+----ThreadPoolExecutor.Worker.java

Worker(Runnable firstTask) {
    setState(-1);
    this.firstTask = firstTask;
    // 调用线程工厂创建线程
    this.thread = getThreadFactory().newThread(this);
}

// Worker 实现了 Runnable 接口
public void run() {
    runWorker(this);
}

+----ThreadPoolExecutor.java
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock();
    boolean completedAbruptly = true;
    try {
        // 循环从任务队列中获取新任务
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 执行新任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        // 线程退出后,进行后续处理
        processWorkerExit(w, completedAbruptly);
    }
}

8、 提交任务

有两种提交任务的方式execute(Runnable command)和submit(Runnable task)。而他们的区别是什么呢?

AbstractExecutorService.java
public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    // 创建任务
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    // 提交任务
    execute(ftask);
    return ftask;
}

最直观的是execute(Runnable command)没有返回值,而submit(Runnable task)返回一个Future。从源码上看submit(Runnable task)最终也是执行了execute(Runnable command)。但是具体是啥区别?

submit在执行过程中与execute不一样,不会抛出异常而是把异常保存在成员变量中,在FutureTask.get阻塞获取的时候再把异常抛出来。通过Future可以很轻易地获得任务的执行情况,比如是否执行完成、是否被取消、是否异常等等。

+---- ThreadPoolExecutor.java
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();

    int c = ctl.get();
    // 如果工作线程数量 < 核心线程数,则创建新线程
    if (workerCountOf(c) < corePoolSize) {
        // 添加工作者对象
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }

    // 缓存任务,如果队列已满,则 offer 方法返回 false。否则,offer 返回 true
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }

    // 添加工作者对象,并在 addWorker 方法中检测线程数是否小于最大线程数
    else if (!addWorker(command, false))
        // 线程数 >= 最大线程数,使用拒绝策略处理任务
        reject(command);
}

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c);
            // 检测工作线程数与核心线程数或最大线程数的关系
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }

    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
        // 创建工作者对象,细节参考上一节所贴代码
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                int rs = runStateOf(ctl.get());
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    // 将 worker 对象添加到 workers 集合中
                    workers.add(w);
                    int s = workers.size();
                    // 更新 largestPoolSize 属性
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            if (workerAdded) {
                // 开始执行任务
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}

代码略多,不过结合线程的创建策略和拒绝策略加上注释,理解主逻辑应该不难。

9、 关闭线程池

我们可以通过shutdown和shutdownNow两个方法关闭线程池。两个方法的区别在于,shutdown 会将线程池的状态设置为SHUTDOWN,同时该方法还会中断空闲线程。shutdownNow 则会将线程池状态设置为STOP,并尝试中断所有的线程。中断线程使用的是Thread.interrupt方法,未响应中断方法的任务是无法被中断的。最后,shutdownNow 方法会将未执行的任务全部返回。

调用 shutdown 和 shutdownNow 方法关闭线程池后,就不能再向线程池提交新任务了。对于处于关闭状态的线程池,会使用拒绝策略处理新提交的任务。

Android中的几种线程池

一般情况下,我们并不直接使用 ThreadPoolExecutor 类创建线程池,而是通过 Executors 工具类去构建线程池。通过 Executors 工具类,我们可以构造5中不同的线程池。下面通过一个表格简单介绍一下几种线程池,如下:

静态构造方法说明
newFixedThreadPool(int nThreads)构建包含固定线程数的线程池,默认情况下,空闲线程不会被回收
newCachedThreadPool()构建线程数不定的线程池,线程数量随任务量变动,空闲线程存活时间超过60秒后会被回收
newSingleThreadExecutor()构建线程数为1的线程池,等价于 newFixedThreadPool(1) 所构造出的线程池
newScheduledThreadPool(int corePoolSize)构建核心线程数为 corePoolSize,可执行定时任务的线程池
newSingleThreadScheduledExecutor()等价于 newScheduledThreadPool(1)

阿里巴巴Android开发手册对线程池使用的建议:

  • 【推荐】ThreadPoolExecutor 设置线程存活时间(setKeepAliveTime),确保空闲时
    线程能被释放。
  • 【强制】线程池不允许使用Executors 去创建,而是通过ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
    说明:
    Executors 返回的线程池对象的弊端如下:
  1. FixedThreadPool 和SingleThreadPool :允许的请求队列长度为
    Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM;
  2. CachedThreadPool 和ScheduledThreadPool :允许的创建线程数量为
    Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
正例:

int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
int KEEP_ALIVE_TIME = 1;
TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>();
ExecutorService executorService = new ThreadPoolExecutor(NUMBER_OF_CORES,
NUMBER_OF_CORES*2, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
taskQueue, new BackgroundThreadFactory(), new DefaultRejectedExecutionHandler());

反例:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

详细介绍每个参数的使用理解:Android中创建线程池 - 简书

----使用----

线程池封装:https://download.csdn.net/download/hdhhd/86812781

1.新建项目,下载上面封装的线程池 添加到项目

2.使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb1"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/style1"
            android:secondaryProgress="0" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#00BCD4">

            <Button
                android:id="@+id/btn1"
                android:layout_width="60dp"
                android:layout_height="36dp"
                android:background="@null"
                android:enabled="false"
                android:text="下载"
                android:textColor="#ffffff"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/text_name1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="namwe" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb2"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/style1"
            android:secondaryProgress="0" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#4CAF50">

            <Button
                android:id="@+id/btn2"
                android:layout_width="60dp"
                android:layout_height="36dp"
                android:background="@null"
                android:enabled="false"
                android:text="下载"
                android:textColor="#ffffff"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/text_name2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="namwe" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb3"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/style1"
            android:secondaryProgress="0" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#8BC34A">

            <Button
                android:id="@+id/btn3"
                android:layout_width="60dp"
                android:layout_height="36dp"
                android:background="@null"
                android:enabled="false"
                android:text="下载"
                android:textColor="#ffffff"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/text_name3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="namwe" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb4"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/style1"
            android:secondaryProgress="0" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#CDDC39">

            <Button
                android:id="@+id/btn4"
                android:layout_width="60dp"
                android:layout_height="36dp"
                android:background="@null"
                android:enabled="false"
                android:text="下载"
                android:textColor="#ffffff"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/text_name4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="namwe" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb5"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/style1"
            android:secondaryProgress="0" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#009688">

            <Button
                android:id="@+id/btn5"
                android:layout_width="60dp"
                android:layout_height="36dp"
                android:background="@null"
                android:enabled="false"
                android:text="下载"
                android:textColor="#ffffff"
                android:textSize="16dp" />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/text_name5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="namwe" />


    <Button
        android:id="@+id/btn_ok"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="下载"
        android:textColor="#009688"
        android:textSize="16dp" />
</LinearLayout>
package com.bruce.pool;

import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.bruce.pool.thread.DefaultExecutorSupplier;

import org.w3c.dom.Text;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
    private ProgressBar mPb1;
    private ProgressBar mPb2;
    private ProgressBar mPb3;
    private ProgressBar mPb4;
    private ProgressBar mPb5;
    private Button mBtn_ok;
    private TextView text1;
    private TextView text2;
    private TextView text3;
    private TextView text4;
    private TextView text5;


    private final int QWER1 = 100;
    private final int QWER2 = 200;
    private final int QWER3 = 300;
    private final int QWER4 = 400;
    private final int QWER5 = 500;
    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case QWER1:
                    String a = (String) msg.obj;
                    int a1 = msg.arg1;
                    text1.setText(a);
                    mPb1.setProgress(a1);

                    break;
                case QWER2:
                    String b = (String) msg.obj;
                    int b1 = msg.arg1;
                    text2.setText(b);
                    mPb2.setProgress(b1);
                    break;
                case QWER3:
                    String c = (String) msg.obj;
                    int c1 = msg.arg1;
                    text3.setText(c);
                    mPb3.setProgress(c1);
                    break;
                case QWER4:
                    String d = (String) msg.obj;
                    int d1 = msg.arg1;
                    text4.setText(d);
                    mPb4.setProgress(d1);
                    break;
                case QWER5:
                    String e = (String) msg.obj;
                    int e1 = msg.arg1;
                    text5.setText(e);
                    mPb5.setProgress(e1);
                    break;
                default:
                    break;
            }


            return true;
        }
    });

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

        initView();

//        int availableProcessors = Runtime.getRuntime().availableProcessors();
//        Log.i("hzw", "availableProcessors = " + availableProcessors);
//
//        btns.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                submit = DefaultExecutorSupplier.getInstance().forBackgroundTasks().submit(new Runnable() {
//                    @Override
//                    public void run() {
//                        a = Thread.currentThread().getName();
//                        DefaultExecutorSupplier.getInstance().forMainThreadExecutor().execute(new Runnable() {
//                            @Override
//                            public void run() {
//                                a += "===" + Thread.currentThread().getName();
//                                text1.setText(a);
//                            }
//                        });
//                        text1.setText("111111");
//                    }
//                });
//            }
//        });
//
//
//        try {
//            Object a = submit.get();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } catch (ExecutionException e) {
//            e.printStackTrace();
//        }
//
//        //        submit.cancel(true); //取消线程执行

    }


    private void initView() {
        mPb1 = findViewById(R.id.pb1);
        mPb2 = findViewById(R.id.pb2);
        mPb3 = findViewById(R.id.pb3);
        mPb4 = findViewById(R.id.pb4);
        mPb5 = findViewById(R.id.pb5);
        mBtn_ok = findViewById(R.id.btn_ok);
        text1 = findViewById(R.id.text_name1);
        text2 = findViewById(R.id.text_name2);
        text3 = findViewById(R.id.text_name3);
        text4 = findViewById(R.id.text_name4);
        text5 = findViewById(R.id.text_name5);


        mBtn_ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DefaultExecutorSupplier.getInstance().forBackgroundTasks().execute(runnable1);
                DefaultExecutorSupplier.getInstance().forBackgroundTasks().execute(runnable2);
                DefaultExecutorSupplier.getInstance().forBackgroundTasks().execute(runnable3);
                DefaultExecutorSupplier.getInstance().forBackgroundTasks().execute(runnable4);
                DefaultExecutorSupplier.getInstance().forBackgroundTasks().execute(runnable5);
            }
        });
    }

    Runnable runnable1 = new Runnable() {
        @Override
        public void run() {
            int a = 0;
            try {
                while (a <= 100) {
                    a = a + 10;
                    Message msg = Message.obtain();
                    msg.what = QWER1;
                    msg.obj = Thread.currentThread().getName();
                    msg.arg1 = a;
                    handler.sendMessage(msg);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };


    Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            int a = 0;
            try {
                while (a <= 100) {
                    a = a + 10;
                    Message msg = Message.obtain();
                    msg.what = QWER2;
                    msg.obj = Thread.currentThread().getName();
                    msg.arg1 = a;
                    handler.sendMessage(msg);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };


    Runnable runnable3 = new Runnable() {
        @Override
        public void run() {
            int a = 0;
            try {
                while (a <= 100) {
                    a = a + 10;
                    Message msg = Message.obtain();
                    msg.what = QWER3;
                    msg.obj = Thread.currentThread().getName();
                    msg.arg1 = a;
                    handler.sendMessage(msg);
                    Thread.sleep(100);
                }

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


    Runnable runnable4 = new Runnable() {
        @Override
        public void run() {
            int a = 0;
            try {
                while (a <= 100) {
                    a = a + 10;
                    Message msg = Message.obtain();
                    msg.what = QWER4;
                    msg.obj = Thread.currentThread().getName();
                    msg.arg1 = a;
                    handler.sendMessage(msg);
                    Thread.sleep(100);
                }

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

    Runnable runnable5 = new Runnable() {
        @Override
        public void run() {
            int a = 0;
            try {
                while (a <= 100) {
                    a = a + 10;
                    Message msg = Message.obtain();
                    msg.what = QWER5;
                    msg.obj = Thread.currentThread().getName();
                    msg.arg1 = a;
                    handler.sendMessage(msg);
                    Thread.sleep(100);
                }

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

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

进度条样式 style1:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- 背景  gradient是渐变,corners定义的是圆角 -->
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="20dp" />

            <solid android:color="#ffffff" />
        </shape>
    </item>
    <!-- 第二条进度条颜色 -->
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="20dip" />

                <gradient
                    android:angle="90.0"
                    android:centerColor="#009688"
                    android:centerY="0.45"
                    android:endColor="#4CAF50"
                    android:startColor="#8BC34A" />
            </shape>
        </clip>
    </item>
    <!-- 进度条 -->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="20dip" />

                <solid android:color="#CDDC39" />
            </shape>
        </clip>
    </item>

</layer-list>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值