Java的几种线程池介绍

线程池

优点

  1. 重用线程池中的线程,避免线程的创建销毁带来的性能开销。
  2. 控制线程池的最大并发数。
  3. 对线程简单管理:如定时执行以及指定间隔循环执行。

实现

ThreadPoolExecutor方法是线程池的真正实现,下面是它的一个比较常用的构造方法:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue
                          ThreadFactory threadFactory)
  1. corePoolSize
    线程池的核心线程数,默认一直存活,即使没有使用。allowCoreThreadTimeOut属性为true时,当等待时间超
    过keepAliveTime所指定的时长后,闲置的核心线程也会被终止。

  2. maximumPoolSize
    线程池所能容纳的最大线程数,非核心线程数 = maximumPoolSize - corePoolSize。

  3. keepAliveTime
    非核心线程数闲置超过这个时长,就会被回收。

  4. unit
    指定keepAliveTime的时间单位,常用TimeUnit.MILLISECONDS,SECONDS,MINUTES等。

  5. workQueue
    线程池任务队列,通过线程池的execute方法提交的Runnable对象会存储在这里。

  6. threadFactory
    线程工厂,提供创建新线程的功能,只有Thread newThread(Runnable r)一个方法。如:

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};  

执行规则

  • 核心线程没用完时,直接启动核心线程
  • 核心线程已经用完,任务会被插入到任务队列排队。
  • 队列已满时,如果线程数量未达到线程池规定的最大值,就启动一个非核心线程
  • 队列已满时,且线程数量达到线程池规定的最大值,就拒绝执行任务,调用RejectedExecutionHandler的
    rejectedExecution方法通知调用者,默认直接抛出RejectedExecutionException

常用的4类线程池

  1. FixedThreadPool

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

    线程数量固定,只有核心线程,且空闲线程不会被回收,任务队列没有大小限制。

    Runnable command = new Runnable() {
        @Override
        public void run() {
            SystemClock.sleep(2000);
        }
    };
    
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
    fixedThreadPool.execute(command);   
  2. CachedThreadPool

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

    只有非核心线程,线程数量为Integer.MAX_VALUE,空闲线程有60s的超时时长,任务队列相当于空集合,导致
    任何任务都会立即被执行。

    扫描二维码关注公众号,回复: 1502703 查看本文章
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    cachedThreadPool.execute(command);
  3. ScheduledThreadPool

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }

    核心线程数量固定,非核心线程数量不限,非核心线程一空闲就会立即回收,主要用于执行定时任务和固定周
    期的重复任务。

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
        // 2000ms后执行command
        scheduledExecutorService.schedule(command, 2000, TimeUnit.MILLISECONDS);
        // 延迟10ms后,每隔1000ms执行一次command
        scheduledExecutorService.sche·duleAtFixedRate(command, 10, 1000,
                TimeUnit.MILLISECONDS);
  4. SingleThreadExecutor

        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }

    只有一个核心线程,没有非核心线程,任务队列没有大小限制,确保所有任务都在同一线程中按顺序执行。

        ExecutorService singleThreadExcutor = Executors.newSingleThreadExecutor();
        singleThreadExcutor.execute(command);

参考资料

[1] 《Android开发艺术探索》, 任玉刚. https://book.douban.com/subject/26599538/

猜你喜欢

转载自blog.csdn.net/weixin_40255793/article/details/80312584