• JAVA线程池 之 Executors (一) 简介


    一、背景

      线程属于系统稀缺资源,在使用线程时,如果无限制创建线程,达到CPU高负荷时,会导致系统运行缓慢,更有甚者直接宕机。

    在这样的基础上我们希望在使用线程时,竟可能使系统线程数处于一个可控范围,尽可能实现线程的重用。

     

    二、Executors 分析

    Executors 示例  DEMO

      

    /**
     * @author binH
     * @date 2018/01/24
     */
    package org.lsnbin.thread;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadAnalyze {
        
        private    static ExecutorService fexecutor = Executors.newFixedThreadPool(20);
        
        public static void main(String[] args) {
            for (int i = 0; i < 20; i++) {
                fexecutor.execute(new ThreadAnalyze().new Task());
            }
        }
        
        private class Task implements Runnable{
    
            @Override
            public void run() {
                System.out.println("Thread name --> " + Thread.currentThread().getName());
            }
        }
    }

      示例分析:

      1、使用Executors初始化一个包含10个线程的线程池

      2、使用execute方法提交20个任务,打印线程名

      3、负责执行任务的线程的生命周期交由Executors管理。

    三、Executors 内部分析

      Executors是线程池的工厂类,内部基于ThreadPoolExecutor实现,对ThreadPoolExecutor进行封装,并提供相对应方法。

      newFixedThreadPool

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

    初始化一定数量
    的线程池,当corePoolSize=maximumPoolSize时,使用LinkedBlockingQueue作为阻塞队列,不过当线程池不使用时,也不会释放线程。

    newCachedThreadPool

    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    不初始化线程,在需要使用时创建线程,最大允许数为
    Integer.MAX_VALUE,使用SynchronousQueue作为阻塞队列,当线程空闲时keepAliveTime后释放线程。
    容易存在问题:在高并发情况下,一瞬间会创建大量的线程,会出现严重的性能问题。

      newSingleThreadExecutor

     public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    初始化只有一个线程的线程池,如果该线程由于异常结束,会重新创建一个新的线程。线程不过期,使用
    LinkedBlockingQueue作为阻塞队列。唯一个线程可以保证任务的顺序执行。

      newScheduledThreadPool

     public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
        }
    初始化一定数量线程的线程池,线程池中的任务可以在指定的时间内周期性的执行所提交的任务。可用于定期同步。

      newWorkStealingPool  -- JDK1.8

     public static ExecutorService newWorkStealingPool(int parallelism) {
            return new ForkJoinPool
                (parallelism,
                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                 null, true);
        }
    创建持有足够线程的线程池来支持给定的并行级别,并通过使用多个队列来减少竞争,需要指定
    parallelism并行参数,如果没指定,则默认CPU数量。

      ForkJoinPool:支持大任务分解成小任务的线程池,这是Java8新增线程池,通常配合ForkJoinTask接口的子类RecursiveAction或RecursiveTask使用。

     

    四、ThreadPoolExecutor 分析

     public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) {
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.acc = System.getSecurityManager() == null ?
                    null :
                    AccessController.getContext();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }

      参数分析:

      1、corePoolSize

        线程池核心线程数。当线程池提交一个任务时,线程池就会创建一个新线程并执行任务,直到线程池内运行状态的线程数等于corePoolSize。

        当继续有任务提交时,会被放入阻塞队列中。使用 prestartCoreThread() 方法可以提前预创建并启动所有核心线程。

      2、maximumPoolSize

        线程池最大可用线程数。在线程数等于corePoolSize时,如果当前阻塞队列满了,继续提交任务时会创建新的线程并执行任务。前提时线程数小于maximumPoolSize。

      3、keepAliveTime

        线程池中线程空闲存活时间。默认情况下该情况只会在大于corePoolSize时有用。但是只要keepAliveTime值非0,可以通过allowallowCoreThreadTimeOut(boolean value)     方法将超时策略应用于核心线程。

      4、unit

        keepAliveTime存活时间的单位。

      5、workQueue

        用来保存等待被执行的任务的阻塞队列。JDK实现的队列有以下几种:

          ArrayBlockingQueue:基于数组结构的有界阻塞队列,按照FIFO ( 先进先出 ) 排序任务。

          LinkedBlockingQueue:基于链表结构的阻塞队列,按照FIFO ( 先进先出 ) 排序任务。效果比ArrayBlockingQueue好。

          DelayQueue:具有延时执行的无界阻塞队列。

          SynchronousQueue:一个不能存储任何元素的阻塞队列,每个插入的操作必须等待另一个相应的删除操作,否则插入则会一直处于阻塞状态。

                    第二个线程必须等待前一个线程结束。

          PriorityBlockingQueue:具有 优先级的无界阻塞队列。

      6、threadFactory

        创建线程的工厂

        默认工厂实现:

      

     DefaultThreadFactory() {
                SecurityManager s = System.getSecurityManager();
                group = (s != null) ? s.getThreadGroup() :
                                      Thread.currentThread().getThreadGroup();
                namePrefix = "pool-" +
                              poolNumber.getAndIncrement() +
                             "-thread-";
            }

      7、handler

          线程池的饱和策略,用于线程数饱和与阻塞队列已满的情况。有任务继续提交时触发的处理逻辑。线程池提供了4种策略:

          AbortPolicy:直接跑出异常,默认策略。

          DiscardPolicy:直接丢弃任务,不处理。

          DiscardOldestPolicy:丢弃阻塞队列中靠前的旧的任务,执行新的任务。

          CallerRunsPolicy:用调用者的线程来执行任务。

  • 相关阅读:
    Django模板
    创建我的第一个django项目
    python django环境配置与安装
    python第九期学习笔记(装饰器进阶)
    python第九期学习笔记(十二)(线程)
    python第九期学习笔记(装饰器)
    python第九期学习笔记(闭包)
    python第九期学习笔记(十二)(面向对象)
    python第九期学习笔记(十一)(面向对象)
    python第九期学习笔记(十)(模块)
  • 原文地址:https://www.cnblogs.com/binbang/p/8343810.html
Copyright © 2020-2023  润新知