Android 线程池的详细使用和封装

一、线程池的使用缘由及好处:

在android开发中使用多线程异步来处理相关任务,用newThread来创建一个子线程进行处理,会出现许多问题:

1:在任务众多的情况下,系统要为每一个任务创建一个线程,任务执行完毕后销毁每一个线程,会造成线程频繁地创建与销毁。

2:多个线程频繁地创建会占用大量的资源,并且在资源竞争的时候就容易出现问题,同时这么多的线程缺乏一个统一的管理,容易造成界面的卡顿。

3:多个线程频繁地销毁,会频繁地调用GC机制,这会使性能降低,又非常耗时。

总而言之:频繁地为每一个任务创建一个线程,缺乏统一管理,降低性能,并且容易出现问题。

为了解决这些问题,就要用到今天的主角——线程池.

使用线程池使用的好处:

1:对多个线程进行统一地管理,避免资源竞争中出现的问题。

2:对线程进行复用,线程在执行完任务后不会立刻销毁,而会等待另外的任务,这样就不会频繁地创建、销毁线程和调用GC。

3:JAVA提供了一套完整的ExecutorService线程池创建的api,可创建多种功能不一的线程池,使用起来比较方便。

二、几种常用的线程池:

Android中的线程池来源于java,主要是通过Executor 来派生特定类型的线程池,不同类型的线程池有不同的意义。Executor是一个接口,真正地实现为ThreadPoolExecutor,他提供了一系列的参数来配置线程池。不同参数意味着不同的线程池。

线程池分为四种以及一种基本线程池:

ThreadPoolExecutor (基本线程池)

创建一个基本的线程池,之后的各种线程池都是在这种基本线程池的基础上延伸的

创建线程池,主要是利用ThreadPoolExecutor这个类,而这个类有几种构造方法,其中参数最多的一种构造方法如下:

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

corePoolSize: 该线程池中核心线程的数量。

maximumPoolSize:该线程池中最大线程数量。(区别于corePoolSize)

keepAliveTime:非核心线程空闲时要等待下一个任务到来的时间,当任务很多,每个任务执行时间很短的情况下调大该值有助于提高线程利用率。注意:当allowCoreThreadTimeOut属性设为true时,该属性也可用于核心线程。

unit:时间属性的单位

workQueue:任务队列

threadFactory:线程工厂,可用于设置线程名字等等,一般无须设置该参数。

四种线程池:

FixedThreadPool (可重用固定线程数)
①可控制线程最大并发数(线程数固定) 

②超出的线程会在队列中等待 

③只有核心线程,无非核心线程,并且阻塞队列无界

使用优势:能够更快的响应外界的请求参数。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
              0L,TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());

CachedThreadPool (缓存线程池)
特点: 
① 线程数无限制 
② 没有核心线程,都是非核心线程 
优势:比较适合用来执行大量的但是耗时较少的任务。

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                        60L, TimeUnit.SECONDS, 
                new SynchronousQueue<Runnable>());
}

ScheduledThreadPool(定时延时线程池)

使用场景:用于执行定时任务和具有固定周期的重复任务。 

SingleTreadExecutor(单个核心线程)

使用场景:按顺序执行,不需要处理同步的问题

封装工具类:

/**
 * 线程池封装
 *
 * @author SJR
 *        created at 2019/1/5
 */
public class ThreadPoolManager {
    private static ThreadPoolManager mInstance;

public static ThreadPoolManager getInstance() {
    if (mInstance == null) {
        synchronized (ThreadPoolManager.class) {
            if (mInstance == null) {
                mInstance = new ThreadPoolManager();
            }
        }
    }
    return mInstance;
}


/**
 * 核心线程池的数量,同时能够执行的线程数量
 */
private int corePoolSize;
/**
 * 最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
 */
private int maximumPoolSize;
/**
 * 存活时间
 */
private long keepAliveTime = 1;
private TimeUnit unit = TimeUnit.HOURS;
private ThreadPoolExecutor executor;

private ThreadPoolManager() {
    /**
     * 给corePoolSize赋值:当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行(有研究论证的)
     */
    corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
    //虽然maximumPoolSize用不到,但是需要赋值,否则报错
    maximumPoolSize = corePoolSize;
    executor = new ThreadPoolExecutor(
            //当某个核心任务执行完毕,会依次从缓冲队列中取出等待任务
            corePoolSize,
            //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
            maximumPoolSize,
            //表示的是maximumPoolSize当中等待任务的存活时间
            keepAliveTime,
            unit,
            //缓冲队列,用于存放等待任务,Linked的先进先出
            new LinkedBlockingQueue<Runnable>(),
            //创建线程的工厂
        //  Executors.defaultThreadFactory(),
            new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
            //用来对超出maximumPoolSize的任务的处理策略
            new ThreadPoolExecutor.AbortPolicy()
    );
}

/**
 * 执行任务
 *
 * @param runnable
 */
public void execute(Runnable runnable) {
    if (executor == null) {
        //线程池执行者。
        //参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
        executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
            //   Executors.defaultThreadFactory(),
                new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
                new ThreadPoolExecutor.AbortPolicy());
    }
    if (runnable != null) {
        executor.execute(runnable);
    }
}

/**
 * 移除任务
 */
public void remove(Runnable runnable) {
    if (runnable != null) {
        executor.remove(runnable);
    }
}

/**
 * 创建线程的工厂,设置线程的优先级,group,以及命名
 */
private static class DefaultThreadFactory implements ThreadFactory {
    /**
     * 线程池的计数
     */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);

    /**
     * 线程的计数
     */
    private final AtomicInteger threadNumber = new AtomicInteger(1);

    private final ThreadGroup group;
    private final String namePrefix;
    private final int threadPriority;

    DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
        this.threadPriority = threadPriority;
        this.group = Thread.currentThread().getThreadGroup();
        namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        t.setPriority(threadPriority);
        return t;
    }
   }
  }

使用方法:

Runnable testRunnable=  new Runnable(){
    @Override
    public void run(){
    //TODO 相关处理逻辑
    ...
    ···
    }
}

ThreadPoolManager.getInstance().execute(testRunnable));

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值