线程笔记

1.使用线程池时,生产环境中线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式的原因:

   使用Executors创建线程池有三种方式:

      1.newCachedThreadPool():创建缓存线程池。

      当一个任务提交时,corePoolSize为0不创建核心线程,SynchronousQueue是一个不存储元素的队列,可以理解为队里永远是满的,因此最终会创建非核心线程来执行任务。

        对于非核心线程空闲60s时将被回收。因为Integer.MAX_VALUE非常大,可以认为是可以无限创建线程的,在资源有限的情况下容易引起OOM异常

      源码为:

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

      2.newSingleThreadExecutor():创建单线程的线程池。

      当一个任务提交时,首先会创建一个核心线程来执行任务,如果超过核心线程的数量,将会放入队列中,因为LinkedBlockingQueue是长度为Integer.MAX_VALUE的队列,可以认为是无界队列,因此往队列中可以插入无限多的任务,

        在资源有限的时候容易引起OOM异常,同时因为无界队列,maximumPoolSize和keepAliveTime参数将无效,压根就不会创建非核心线程

      源码为:

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

      3.newFixedThreadPool():创建指定线程数的线程池。

      FixedThreadPool是固定核心线程的线程池,固定核心线程数由用户传入,同样是因为LinkedBlockingQueue是长度为Integer.MAX_VALUE的队列,可以认为是无界队列,容易引起OOM异常

      源码为:

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

  以上三种方式都是执行:new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, TimeUnit.MILLISECONDS,runnableTaskQueue);五个参数分别为:核心线程数,最大线程数,存活前最大空闲时间(针对非核心线程),时间单位,任务队列(等待执行任务的队列)

  

执行逻辑:

1.判断核心线程数是否已满,未满则创建线程执行任务

2.若核心线程池已满,判断队列是否满,若未满则加入队列中

3.若队列已满,判断线程池是否已满,若未满创建线程执行任务

4.若线程池已满,则采用拒绝策略处理无法执执行的任务

因此:建议开发者自己使用new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, TimeUnit.MILLISECONDS,runnableTaskQueue, threadFactory,handler);来创建线程池,这样可以根据硬件的不同来设置相对应的参数。

 

 

2.DCL(Double check Lock)双检查锁,先检查缓存中对象是否存在,不存在则加锁,然后再判断缓存中对象是否存在,存在则直接返回,不存在则从数据库中查询,然后保存到缓存中

 

posted on 2020-07-11 17:20  永不宕机  阅读(152)  评论(0编辑  收藏  举报

导航