文档章节

Android多线程操作——线程池管理综述

赵子龙
 赵子龙
发布于 2016/07/24 04:57
字数 1844
阅读 492
收藏 9
点赞 0
评论 1

题记——

        难过了,悄悄走一走;

        伤心了,默默睡一觉;

        优雅不是训练出来的,而是一种阅历;

        淡然不是伪装出来的,而是一种沉淀;

 

        时间飞逝,老去的只是我们的容颜;

        时间仿佛一颗灵魂,越来越动人;

其他站点:

        1、回享每一时刻  http://jingyan.baidu.com/article/25648fc193fcbe9190fd004f.html

        2、回眸每一点钟 http://blog.csdn.net/zl18603543572/article/details/52012122

1、简述:

    在多线程的世界中,是那么的神奇 与 高效以及合理;

2、创建线程池实例

    官方推荐使用Executors类工厂方法来创建线程池管理,Executors类是官方提供的一个工厂类,里面封装了好多功能不一样的线程池,从而使得我们创建线程池非常的简单:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3、使用线程池来管理任务

4、Executors核心创建说明

可以看到1 - 3 创建线程池的方法中,全部是创建了ThreadPoolExecutor这个对象实例,不同的只是构造中的参数不一至,而在4 与5 ,从其继承的角度来看


public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {

   

可以看到其实质也是继承于ThreadPoolExecutor这个对象实例。

也就是说上述一种类型的线程池其都是 ThreadPoolExecutor子类,其实直接创建ThreadPoolExecutor实例对象,只需要传入相对应的配制参数,就可以创建出来与上述五种效果相一至的线程池管理,只不过是在书写的时候太过于繁锁。

 /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

 

5、ThreadPoolExecutor简述

从上述创建ThreadPoolEecutor实例的构造来说,

6、自定义线程池



    /**
     * 创建线程池也是需要资源的,所以线程池内线程数量的大小也会影响系统的性能,
     * 大了反而浪费资源,小了反而影响系统的吞吐量,
     * 所以我们创建线程池需要把握一个度才能合理的发挥它的优点,
     * 通常来说我们要考虑的因素有CPU的数量、内存的大小、并发请求的数量等因素,按需调整。
     *通常核心线程数可以设为CPU数量+1,而最大线程数可以设为CPU的数量*2+1。
     */
    private void customThreadFunction() {
        /**
         * 获取CPU数量
         */
        int processors = Runtime.getRuntime().availableProcessors();

        /**
         * 核心线程数量
         */
        int corePoolSize =processors + 1;
        /**
         * 最大线程数量
         */
        int maximumPoolSize =  processors * 2 + 1;
        /**
         * 空闲有效时间
         */
        long keepAliveTime = 60;
        /**
         * 创建自定义线程池
         */

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new PriorityBlockingQueue());

        /**
         * 添加执行任务
         */
        for (int i=1;i<=20;i++){
            final int prites = i;
            threadPoolExecutor.execute(new CustomRunnable(prites){

                @Override
                public void doRun() {

                    String name = Thread.currentThread().getName();
                    System.out.println("curentThread name is "+name +"and prites is "+prites);
                    SystemClock.sleep(1000);

                }
            });
        }
    }
 public abstract class CustomRunnable implements Runnable,Comparable<CustomRunnable> {
        private int priority;

        public CustomRunnable(int priority) {
            if (priority<0)
            throw new IllegalArgumentException();
            this.priority = priority;
        }

        @Override
        public int compareTo(CustomRunnable another) {
            int my = this.getPriority();
            int other = another.getPriority();
            if (my>other){
                return  -1;
            }else{
                return 0;
            }

        }



        @Override
        public void run() {
            doRun();
        }

        public abstract void doRun();

        public int getPriority() {
            return priority;
        }
    }

 

7、自定义扩展线程池


public class CustomExpanThreadPool extends ThreadPoolExecutor {

    private CustomExpanThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public static CustomExpanThreadPool getInstance() {
        /**
         * 获取CPU数量
         */
        int processors = Runtime.getRuntime().availableProcessors();

        /**
         * 核心线程数量
         */
        int corePoolSize = processors + 1;
        /**
         * 最大线程数量
         */
        int maximumPoolSize = processors * 2 + 1;
        /**
         * 空闲有效时间
         */
        long keepAliveTime = 60;
        /**
         * 创建自定义线程池
         */

        return new CustomExpanThreadPool(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new PriorityBlockingQueue());

    }

    /**
     * 用于控制线程开始与停止执行的方法
     */
    private boolean isPaused;
    private ReentrantLock pauseLock = new ReentrantLock();
    private Condition unpaused = pauseLock.newCondition();


    /**
     * 任务执行前要执行的方法
     *
     * @param t
     * @param r
     */
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        System.out.println(Thread.currentThread().getName() + "  任务执行开始 ");
        pauseLock.lock();
        try {
            while (isPaused) unpaused.await();
        } catch (InterruptedException ie) {
            t.interrupt();
        } finally {
        }
    }

    /**
     * 任务执行后要执行的方法
     *
     * @param r
     * @param t
     */
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        System.out.println(Thread.currentThread().getName() + "  任务执行over ");
    }

    /**
     * 线程池关闭后要执行的方法
     */
    @Override
    protected void terminated() {
        super.terminated();
    }

    /**
     * 暂停执行任务的方法
     */
    public void pause() {
        pauseLock.lock();
        try {
            isPaused = true;
        } finally {
            pauseLock.unlock();
        }
    }

    /**
     * 恢复执行任务的方法
     */
    public void resume() {
        pauseLock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        } finally {
            pauseLock.unlock();
        }
    }
}

使用:

 private void customThreadFunction2() {

        CustomExpanThreadPool threadPoolExecutor = CustomExpanThreadPool.getInstance();

        /**
         * 添加执行任务
         */
        for (int i=1;i<=20;i++){
            final int prites = i;
            threadPoolExecutor.execute(new CustomRunnable(prites){

                @Override
                public void doRun() {

                    String name = Thread.currentThread().getName();
                    System.out.println("curentThread name is "+name +"and prites is "+prites);
                    SystemClock.sleep(1000);

                }
            });
        }
    }

8、自定义线程池与可控制取消的任务

首先创建自定义的线程池(与标签7)


    /**
     * CPU数量
     */
    private int process = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数量
     */
    private int corePoolSize = process + 1;
    /**
     * 最大线程数量
     */
    private int maxPoolSize = process * 2 + 1;
    /**
     * 空闲有效时间
     */
    private long keepAliveTime = 60;
    /**
     * 自定义线程池
     */
    private ThreadPoolExecutor mThreadPoolExecutor;

    /**
     * 用于保存任务的集合
     */
    private Map<String, Future<Integer>> mThreadFutureTaskMap;

    private ThreadPoolManager(){
        if (mThreadPoolExecutor == null) {
            synchronized (ThreadPoolManager.class){
                if (mThreadPoolExecutor == null) {
                    init();
                }
            }
        }
    }
    public void init() {

        /**
         * 初始化创建线程池
         */
        mThreadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
                                                        maxPoolSize,
                                                        keepAliveTime,
                                                        TimeUnit.SECONDS,
                                                        new LinkedBlockingQueue<Runnable>()) {

            private boolean isPaused;
            private ReentrantLock pauseLock = new ReentrantLock();
            private Condition unpaused = pauseLock.newCondition();

            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                pauseLock.lock();
                try {
                    while (isPaused) unpaused.await();
                } catch (InterruptedException ie) {
                    t.interrupt();
                } finally {
                    pauseLock.unlock();
                }
            }

            /**
             * 暂停
             */
            public void pauseThreadPool() {
                pauseLock.lock();
                try {
                    isPaused = true;
                } finally {
                    pauseLock.unlock();
                }
            }

            /**
             * 恢复任务
             */
            public void resumeThreadPool() {
                pauseLock.lock();
                try {
                    isPaused = false;
                    unpaused.signalAll();
                } finally {
                    pauseLock.unlock();
                }
            }

        };
        /**
         * 初始化保存任务的集合
         */
        mThreadFutureTaskMap = new HashMap<>();
    }

然后就是创建用于控制任务的回调



public abstract class ThreadPoolCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        runCall();
        return 1;
    }
    public abstract void  runCall();
}

关于ThreadPoolCallable 

可以看到这里是继承于Callable,call方法中的回调返回的信息可以通过些任务对象回调得到,当然异步方法也是在call方法中执行

然后就是向线程池内添加任务


    /**
     * 添加单个任务
     *@param keyTag 任务的标签
     * @param task 任务
     * @return  任务对象
     */
    public Future addTask(ProrityPoolCallable task, String keyTag) {
        //添加并提交任务
        RunnableFuture futureTask = (RunnableFuture) mThreadPoolExecutor.submit(task);
        //将任务添加到集合中
        Future put = mThreadFutureTaskMap.put(keyTag, futureTask);
        return futureTask;
    }

        将每个任务提交给线程池管理,然后会返回一个Future对象,看其源码会发现其最终继承Runable对象,然后呢我们将这个Future对象以key,value形式存储到Map集合中去,目的是当我们要取消一个任务的时候,当这个任务已经被提交到线程池中,未执行或者是正在执行,我们都可以通过传的KEY,然后再从集合中取出Key对应的Futureccf对象,然后执行cancel方法,就可以取消这个任务了

取消任务


    /**
     * 移除单个任务
     * @param key   任务标签
     * @return  true 为成功
     */
    public boolean removeTask(String key) {
        //任务移除标识
        boolean cancel = false;
        //根据KEY来获取对应的Future对象
        Set<String> keySet = mThreadFutureTaskMap.keySet();
        if (keySet.contains(key)) {
            Future<Integer> future = mThreadFutureTaskMap.get(key);
            //当前的任务已经被执行完毕,不进行操作
            if (!future.isCancelled()) {
                cancel = future.cancel(true);
                if (cancel) {
                    //当取消成功后,从本地Key集合中移除标识
                    mThreadFutureTaskMap.remove(key);
                }
            }else{
                mThreadFutureTaskMap.remove(key);
            }
        }
        return cancel;
    }

 

© 著作权归作者所有

共有 人打赏支持
赵子龙
粉丝 3
博文 10
码字总数 21302
作品 0
海淀
项目经理
加载中

评论(1)

gsod
gsod
不错
进程线程

Android 一起来看看 ThreadLocal ThreadLocal 是一个线程内部的数据存储类,通过它可以在 指定的线程中 存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则...

掘金官方 ⋅ 01/09 ⋅ 0

Android技能树 — Rxjava取消订阅小结(1):自带方式

前言: Android技能树系列: Android基础知识 Android技能树 — 动画小结 Android技能树 — View小结 Android技能树 — Activity小结 Android技能树 — View事件体系小结 Android技能树 — ...

青蛙要fly ⋅ 05/29 ⋅ 0

Android开源框架源码鉴赏:EventBus

作者:郭孝星 校对:郭孝星 关于项目 Android Open Framework analysis项目主要用来分析Android平台主流开源框架的源码与原理实现。 文章目录 一 注册订阅者 二 发布事件Event 三 接收事件E...

郭孝星 ⋅ 03/27 ⋅ 0

Android异步加载全解析之使用AsyncTask

Android异步加载全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅可以对并发线程进行管理,更可以提高他们执行的效率,优化整个App。当然我们可以自...

eclipse_xu ⋅ 2015/03/19 ⋅ 0

2018 Android 面试心得,已拿到 offer

code小生,一个专注于 Android 领域的技术分享平台 作者:huisonma 链接:https://www.jianshu.com/p/855ff21e0a13 声明:本文是 huisonma 原创,转发等请联系原作者授权。 从 16 年毕业至今...

h176nhx7 ⋅ 04/16 ⋅ 0

RxJava 1.x使用与理解

RxJava 1.x使用与理解——2018.5.22 前一段时间,项目引入RxJava,用起来很简单,但是对原理不甚理解,于是参考各种资料,对照源码,进行了深入学习,写在这里,希望对看到的小伙伴有所帮助 ...

lichuangnk ⋅ 06/12 ⋅ 0

android -------- java虚拟机和Dalvik虚拟机

java虚拟机 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚...

切切歆语 ⋅ 04/29 ⋅ 0

基于JSON RPC的一种Android跨进程调用解决方案了解一下?

基于JSON RPC的一种Android跨进程调用解决方案了解一下? 基于JSON RPC的一种Android跨进程调用解决方案了解一下? 简介 今天上午,看票圈有朋友分享爱奇艺的跨进程通信框架——Andromeda,觉...

流水不腐小夏 ⋅ 05/30 ⋅ 0

gis-luq/RuntimeViewer3D

RuntimeViewer —— 基于ArcGIS Runtime 100.x开发的移动应用程序框架 组件式开发框架,兼容手机、平板多种设备。 平板模式 手机模式 如何快速运行应用程序? 使用git工具下来工程并将工程导...

gis-luq ⋅ 06/20 ⋅ 0

Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 1分钟前 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 8分钟前 ⋅ 0

Python 优化 回溯下降算法

使用sympy构造表达式,实现回溯下降算法 画出函数图像,先使用暴力搜索,找到最小值约为2.5左右 然后选定初始点,开始进行回溯搜索,下降方向为负梯度方向 完整代码 from matplotlib import...

阿豪boy ⋅ 12分钟前 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 14分钟前 ⋅ 0

用接口模拟可伸缩枚举(34)

1、枚举的可伸缩性最后证明都不是什么好点子 扩展类型的元素是基本类型实例,基本类型的实例却不是扩展类型的元素,很混乱 目前还没有很好的方法来枚举基本类型的所有元素,及其扩展 可伸缩性...

职业搬砖20年 ⋅ 17分钟前 ⋅ 0

Ubuntu18.04 IDEA快捷键无法使用

IDEA默认的回退到上一视图的快捷键是Ctrl + Alt + Left,在ubuntu中这个快捷键被占用了,在16.04中可以在界面中取消这个快捷键,但是18.04就看不到了,可以使用以下命令解决 gsettings set ...

Iceberg_XTY ⋅ 22分钟前 ⋅ 0

如何解决s权限位引发postfix及crontab异常

一、问题现象 业务反馈某台应用服务器,普通用户使用mutt程序发送邮件时,提示“postdrop warning: mail_queue_enter: create file maildrop/713410.6065: Permission denied”,而且普通用法...

问题终结者 ⋅ 34分钟前 ⋅ 0

Unable to load database on disk

由于磁盘空间满了以后,导致zookeeper异常退出,清理磁盘空间后,zk启动报错,信息如下: 2018-06-25 17:18:46,904 INFO org.apache.zookeeper.server.quorum.QuorumPeerConfig: Reading co...

刀锋 ⋅ 53分钟前 ⋅ 0

css3 box-sizing:border-box 实现div一行多列

<!DOCTYPE html><html><head><style> div.container{ background:green; padding:10px 10px;}div.box{box-sizing:border-box;-moz-box-sizing:border-box; /* Fir......

qimh ⋅ 59分钟前 ⋅ 0

Homebrew简介和基本使用

一、Homebrew是什么 Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径...

说回答 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部