美文网首页
Android 线程池的封装

Android 线程池的封装

作者: GODANDDEVIL | 来源:发表于2020-06-23 17:59 被阅读0次

GlobalThreadPools.java:

/**
 * 全局使用的线程池
 */
public class GlobalThreadPools {

    private static String TAG = GlobalThreadPools.class.getSimpleName();

    private static ExecutorService THREAD_POOL_EXECUTOR;//线程池

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//CPU数量
    private static final int CORE_POOL_SIZE = CPU_COUNT;//核心线程数
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2;//最大线程数
    private static final int KEEP_ALIVE_SECONDS = 60;//线程闲置后的存活时间
    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(CPU_COUNT);//任务队列
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {//线程工厂
        private final AtomicInteger mCount = new AtomicInteger(1);
        public Thread newThread(Runnable r) {
            return new Thread(r, "MangoTask #" + mCount.getAndIncrement());
        }
    };

    //初始化线程池
    private void initThreadPool() {
        THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory, new RejectedHandler()){
            @Override
            public void execute(Runnable command) {
                super.execute(command);
                Log.e(TAG,"ActiveCount="+getActiveCount());
                Log.e(TAG,"PoolSize="+getPoolSize());
                Log.e(TAG,"Queue="+getQueue().size());
            }
        };
    }

    private static class RejectedHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            //可在这里做一些提示用户的操作
//            Log.v("+++","is over the max task...");
        }
    }

    private static GlobalThreadPools instance;
    private GlobalThreadPools(){
        initThreadPool();
    }
    public static GlobalThreadPools getInstance(){
        if (instance == null) {
            instance = new GlobalThreadPools();
        }
        return instance;
    }

    public void execute(Runnable command){
        THREAD_POOL_EXECUTOR.execute(command);
    }

//    /**
//     * 通过interrupt方法尝试停止正在执行的任务,但是不保证真的终止正在执行的任务
//     * 停止队列中处于等待的任务的执行
//     * 不再接收新的任务
//     * @return 等待执行的任务列表
//     */
//    public List<Runnable> shutdownNow(){
//        return THREAD_POOL_EXECUTOR.shutdownNow();
//    }
//
//    /**
//     * 停止队列中处于等待的任务
//     * 不再接收新的任务
//     * 已经执行的任务会继续执行
//     * 如果任务已经执行完了没有必要再调用这个方法
//     */
//    public void shutDown(){
//        THREAD_POOL_EXECUTOR.shutdown();
//        sPoolWorkQueue.clear();
//    }

}

调用:

//线程池开启任务
        GlobalThreadPools.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                  .......
            }
        });

线程池
线程池概念来源于Java中的Executor,它是一个接口,真正的实现为ThreadPoolExecutor。ThreadPoolExecutor提供了一系列参数来配置线程池。
优点
1:重用线程池中的线程,线程在执行完任务后不会立刻销毁,而会等待另外的任务,这样就不会频繁地创建、销毁线程和调用GC。。
2:有效控制线程池的最大并发数,避免大量线程抢占资源出现的问题。
3:对多个线程进行统一地管理,可提供定时执行及指定间隔循环执行的功能。
ThreadPoolExecutor 有多个重载方法,但最终都调用了这个构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数:
corePoolSize:线程池中核心线程的数量;为了内存优化,在线程池维护了几个重要的线程,不达到一定条件不开辟其余线程
maximumPoolSize :线程池中最大线程数量:这个数量是包括核心线程的,当线程池中的正在执行的线程池达到了这个数字,再提交线程如果你不做特殊处理将会抛出异常
keepAliveTime:非核心线程的超时时长;当线程池中的非核心线程闲置时间超过这个值代表的时间后,将会被回收;同时如果调用ThreadPoolExecutor.allowCoreThreadTimeOut(true),那么核心线程也会符合这个设置
unit:keepAliveTime值的单位,可以是时分秒等
workQueue:存放待执行的线程;你通过execute方法提交线程,但是这些线程还没达到执行条件,那么就会保存在这个队列里
threadFactory:创建线程池的工厂;在这个工厂里,我们可以指定线程的一些信息
handler:线程提交拒绝策略;通常是线程池中的正在执行的线程数量已经达到了最大线程数或线程池关闭,如果不传,默认是抛出一个RejectedExecutionException,所以最好传下

推荐使用 Executors 的工厂方法来创建线程池,通过直接或间接的配置 ThreadPoolExecutor 的参数来构建线程池,常用的线程池有如下 4 种,newFixedThreadPool ,newCachedThreadPool,
newScheduledThreadPool 和 newSingleThreadExecutor。

  1. FixedThreadPool 只有核心线程,并且数量是固定的,也不会被回收,能更快地响应外界请求。
  2. SingleThreadPool 只有一个核心线程,确保所有任务都在同一线程中按顺序完成。因此不需要处理线程同步的问题。
  3. CachedThreadPool 只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则利用空闲线程处理任务,任何任务都会被立即执行。
  4. ScheduledThreadPool 核心线程数固定,非核心线程数没有限制,主要用于执行定时任务以及有固定周期的重复任务。

ThreadPoolExecutor 执行任务时大致遵循如下流程:
1.如果线程池中的线程数未达到核心线程数,则会立马启用一个核心线程去执行。
2.如果线程池中的线程数已经达到核心线程数,且任务队列workQueue未满,则将新线程放入workQueue中等待执行。
3.如果线程池中的线程数已经达到核心线程数但未超过线程池规定最大值,且workQueue已满,则开启一个非核心线程来执行任务。
4.如果线程池中的线程数已经超过线程池规定最大值,则拒绝执行该任务,采取饱和策略,并抛出RejectedExecutionException异常。

线程池大小:(N为CPU数量)
如果是CPU密集型应用,则线程池大小设置为N+1
如果是IO密集型应用,则线程池大小设置为2N+1
I/O密集型
指的是系统的CPU效能相对硬盘/内存的效能要好,大部分的状况是 CPU 在等 I/O (硬盘/内存) 的读/写, CPU Loading 不高。
CPU密集型
指的是系统的 硬盘/内存 效能 相对 CPU 的效能 要好,大部分的状况是 CPU Loading 100%,CPU 要读/写 I/O (硬盘/内存),I/O在很短的时间就可以完成,而 CPU 还有许多运算要处理,CPU Loading 很高。
获取CPU数量的方法为:
Runtime.getRuntime().availableProcessors();

摘自:
https://blog.csdn.net/qq_30993595/article/details/84324681

相关文章

网友评论

      本文标题:Android 线程池的封装

      本文链接:https://www.haomeiwen.com/subject/jpmvtktx.html