Welcome everyone

线程池

java 汪明鑫 992浏览 1评论
任务数量多时,用线程池更快
先看下Executor整体架构
那么Executors是什么?
类比Array、Arrays,Collection、Collections
-s表示工具类
用底层,看顶层,想要用一个框构的底层、实现类,先要看其最顶层
public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

就是执行任务

 

Executors

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

返回固定数量的线程池

 

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

返回一个根据实际情况调整线程个数的线程池,不限制最大最大线程数量。每一个空闲线程会在60s后自动回收

 

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

创建一个线程的线程池

 

  • java.util.concurrent.Executors#newScheduledThreadPool(int)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

用来调度即将执行任务的线程池

 

我们发现都调用了 ThreadPoolExecutor

 

如何理解corePoolSize(核心线程数量)和maximumPoolSize(非核心线程数量)?

比如一家餐厅平时有5个厨师做菜  (corePoolSize=5)

但逢年过节来吃饭的人特别多,于是又招了3个厨师,考虑到员工成本问题,又不会招太多(maximumPoolSize=8)

当忙的几天过去了,又把新招的3个辞退掉,又恢复到corePoolSize

 

 

 

怎么理解阻塞队列?

分为有界队列和无界队列

1)使用有界队列时,有新任务要执行,若线程池线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,把任务加入队列,

若队列已满,则在总线程数小于maximumPoolSize的情况下,创建新的线程,若线程数大于maximumPoolSize,则执行拒绝策略。

2)使用无界队列时,如LinkedBlockingQueue,任务不断入队列,直到系统资源耗尽

 

什么是拒绝策略?

java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy

运行当前被丢弃的任务

java.util.concurrent.ThreadPoolExecutor.AbortPolicy

直接抛出异常

java.util.concurrent.ThreadPoolExecutor.DiscardPolicy

丢弃无法处理的任务,不给予任何处理

java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

丢弃最老的一个请求

 

也可以自定义拒绝策略

 

除了可以使用Executors提供的线程池,也可以使用自定义线程池

 

 

 

1)配置线程池时,CPU 密集型任务可以少配置线程数,大概和机器的 cpu 核数相 当,可以使得每个线程都在执行任务。
2)IO 密集型任务则由于需要等待 IO 操作,线程并不是一直在执行任务,则配置尽 可能多的线程,2*cpu 核数。
3)有界队列和无界队列的配置需区分业务场景,一般情况下配置有界队列,在一些 可能会有爆发性增长的情况下使用无界队列。
4)任务非常多时,使用非阻塞队列使用 CAS 操作替代锁可以获得好的吞吐量。 synchronousQueue 吞吐率最高。

转载请注明:汪明鑫的个人博客 » 线程池

喜欢 (0)

说点什么

1 评论 在 "线程池"

提醒
avatar
排序:   最新 | 最旧 | 得票最多
wpDiscuz