线程池

83 阅读4分钟

前言

Executors(java.util.concurrent.Executors)框架,是Java中用于创建线程池的工厂类。CachedThreadPool FixedThreadPool ScheduledThreadPool SingleThreadExecutor等。

  1. newCachedThreadPool():根据需要创建新线程的线程池
  2. newFixedThreadPool(int n):固定线程数的线程池,超过的任务会在队列中等待
  3. newScheduledThreadPool(int corePoolSize):延迟执行任务,或周期性执行
  4. newSingleThreadExecutor():使用单个worker线程的线程池,无界队列运行该线程

线程池生命周期:创建、运行、关闭三个阶段。

ThreadPoolExecutor

实现自定义线程池。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
  • corePoolSize:核心线程数,线程池维护的最小线程数。
  • maximumPoolSize:最大线程数,允许的最大线程数。
  • keepAliveTimes:当前线程池线程数量超过核心线程数时,多余空闲线程在终止前等待新任务的最长时间。
  • unit:keepAliveTimes时间单位
  • workQueue:等待执行任务的阻塞队列
  • threadFactory:线程工厂
  • defaultHandler:拒绝策略,达到最大线程数后的拒绝策略。

image.png

自定义线程池:子线程切换、主线程切换、延迟任务、周期任务

package com.georege.tools;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 异步任务执行工具类
 *
 */

public class TaskExecutor {
    /**
     * 当前设备的CPU数
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    /**
     * 当前线程池默认的线程数
     */
    private static final int CORE_POOL_SIZE = CPU_COUNT + 3;

    /**
     * 线程池最大线程数
     */
    private static final int MAX_POOL_SIZE = CPU_COUNT * 2 + 1;

    /**
     * 调度任务最大线程池数
     */
    private static final int MAX_SCHEDULED_POOL_SIZE = 2;

    /**
     * 是否keep alive
     */
    private static final int KEEP_ALIVE = 1;

    /**
     * 线程池
     */
    private static ExecutorService sExecutorService = null;
    /**
     * 延时定时线程池
     */
    private static ScheduledThreadPoolExecutor sScheduledThreadPoolExecutor = null;
    /**
     * 主线程handler
     */
    private static Handler sMainHandler = null;

    /**
     * 线程池构造
     */
    private synchronized static void ensureThreadPoolExecutor() {
        if (sExecutorService == null) {
            // 线程池构造7个参数:核心线程数;最大线程数;线程空闲时间;时间单位;存放任务队列;创建线程工厂;
            // 当任务满了后再次提交任务时的策略(丢弃阻塞队列中靠前的任务,并执行当前任务)
            sExecutorService = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
                    new LinkedBlockingDeque<Runnable>(), new DefaultThreadPoolFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
        }
    }

    /**
     * 延时定时线程池,任务延期执行或定期执行
     */
    private synchronized static void ensureScheduledThreadPoolExector() {
        if (sScheduledThreadPoolExecutor == null) {
            // 继承ThreadPoolExecutor。
            // 核心线程数;拒绝策略(直接抛出异常,阻止系统正常运行)
            sScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(MAX_SCHEDULED_POOL_SIZE, new ThreadPoolExecutor.AbortPolicy());
        }
    }

    /**
     * 初始化主线程handler
     */
    private synchronized static void ensureMainHandler() {
        if (sMainHandler == null) {
            sMainHandler = new Handler(Looper.getMainLooper());
        }
    }

    /**
     * 执行异步任务,默认线程池
     *
     * @param task 需要异步执行的任务
     */
    public static Future<?> executeTask(Runnable task) {
        ensureThreadPoolExecutor();
        return sExecutorService.submit(task);
    }

    /**
     * 执行异步任务,并获取结果,默认线程池
     *
     * @param task 需要异步执行的任务
     * @return 任务执行结果,需要自行处理异常
     */
    public static <T> Future<?> executeTaskWithResult(Callable<T> task) {
        ensureThreadPoolExecutor();
        return sExecutorService.submit(task);
    }

    /**
     * 延时执行一个异步任务
     *
     * @param delay 延时时间,毫秒
     * @param task  需要执行的异步任务
     * @return 延时执行结果,不需要可不理会
     */
    public static ScheduledFuture<?> scheduledTask(long delay, Runnable task) {
        ensureScheduledThreadPoolExector();
        return sScheduledThreadPoolExecutor.schedule(task, delay, TimeUnit.MILLISECONDS);
    }

    /**
     * 周期执行异步任务
     *
     * @param task      需要周期执行的异步任务
     * @param initDelay 初始延时, 毫秒
     * @param period    周期,毫秒
     */
    public static ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initDelay, long period) {
        ensureScheduledThreadPoolExector();
        return sScheduledThreadPoolExecutor.scheduleAtFixedRate(task, initDelay, period, TimeUnit.MILLISECONDS);
    }

    /**
     * 在UI线程中执行任务
     *
     * @param task 需要执行的任务
     */
    public static void runTaskOnUiThread(Runnable task) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            task.run();
        } else {
            ensureMainHandler();
            sMainHandler.post(task);
        }
    }

    /**
     * 在UI线程中延时执行任务
     *
     * @param delay 延时时间,毫秒
     * @param task  需要执行的任务
     */
    public static void scheduledTaskOnUiThread(long delay, Runnable task) {
        ensureMainHandler();
        sMainHandler.postDelayed(task, delay);
    }

    /**
     * 移除UI线程延时任务
     *
     * @param task
     */
    public static void removeTaskOnUiThread(Runnable task) {
        ensureMainHandler();
        sMainHandler.removeCallbacks(task);
    }

    /**
     * 清理并回收线程池占用的资源(非必要时无需调用)
     */
    public static void shutdown() {
        if (sExecutorService != null) {
            sExecutorService.shutdown();
            sExecutorService = null;
        }
    }

    /**
     * 默认的线程池工厂,线程使用默认优先级
     */
    private static class DefaultThreadPoolFactory implements ThreadFactory {

        /**
         * 当前线程池号
         */
        private static final AtomicInteger THREAD_POOL_NUM = new AtomicInteger(1);
        /**
         * 线程所属分组
         */
        private final ThreadGroup group;
        /**
         * 线程代号
         */
        private final AtomicInteger threadNum = new AtomicInteger(1);

        /**
         * 当前总线程数
         */
        private final AtomicInteger totalThreadNum = new AtomicInteger(1);

        /**
         * 线程名前缀
         */
        private final String namePrefix;

        /**
         * 默认线程工厂
         */
        DefaultThreadPoolFactory() {
            SecurityManager s = System.getSecurityManager();
            group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "pool-id-" + THREAD_POOL_NUM.getAndIncrement();
        }

        @Override
        public Thread newThread(@NonNull Runnable r) {
            Thread thread = new Thread(group, r,
                    namePrefix + " thread-id-" + threadNum.getAndIncrement() + " total-thread-num-" + totalThreadNum.getAndIncrement());
            thread.setPriority(Thread.NORM_PRIORITY);
            if (thread.isDaemon()) {
                thread.setDaemon(false);
            }
            return thread;
        }
    }
}

总结

  1. ScheduledThreadPoolExecutor最大线程数是Integer.MAX_VALUE
  2. ScheduledThreadPoolExecutor工作队列是DelayedWorkQueue按执行时间作为比较优先队列,使用二叉堆数据结构,每次take任务都拿根节点的任务(距离执行时间最近的)。 3.ScheduledThreadPoolExecutor中,period=0 抛出异常;scheduleAtFixedRate period>0 按照第一个任务起点,时间顺序执行,不考虑任务花费的时间;scheduleWithFixedDelay period<0 按照上次任务执行完成的时间延迟period时间执行