美文网首页Android开发经验谈程序员Android开发
什么是线程池?为什么要使用线程池?如何使用?

什么是线程池?为什么要使用线程池?如何使用?

作者: 一团捞面 | 来源:发表于2020-03-16 13:45 被阅读0次

    1. 什么是线程池?

    线程池其实就是将多个线程对象放到一个容器当中。

    2. 为什么使用线程池?

    可以重用线程,减少创建和销毁线程带来的消耗。

    3. 如何使用线程池?

    要想知道如何使用线程池,就要先知道线程池的种类有多少种?线程池大概有以下几种:

    1. ThreadPoolExecutor
    2. FixedThreadPool
    3. CahcedThreadPool
    4. SingleThreadExecutor
    5. ScheduledThreadPool

    以下介绍这几种线程池的用法:

    3.1 ThreadPoolExecutor

    ThreadPoolExecutor 是线程池真正的实现方法,以下是 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 线程池容纳最大的线程数
    keepAliveTime 非核心线程闲置时的超时时长
    unit keepAliveTime 参数的时间单位
    workQueue 线程池中的任务队列
    threadFactory 线程工厂,为线程池提供创建新线程的功能

    3.2 FixedThreadPool

    一种固定线程数量的线程池。

    可以通过 Executors 的 newFixedThreadPool() 方法创建:

    ExecutorService pool = Executors.newFixedThreadPool(4);
    

    newFixedThreadPool() 具体实现:

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

    可以看出 newFixedThreadPool() 是通过创建 ThreadPoolExecutor 来创建线程池的。

    并且因为 corePoolSize 和 maximumPoolSize 是一样的,所以这种线程池只有核心线程,任务超出线程数后,会在队列中等待。

    具体使用如下:

    ExecutorService pool = Executors.newFixedThreadPool(4);
    
    Runnable task = new Runnable() {
         @Override
          public void run() {
              System.out.println("haha");  
          }
    };
    
    pool.execute(task);
    

    3.3 CahcedThreadPool

    一种线程数量不定的线程池。

    可以通过 Executors 的 newCachedThreadPool() 方法创建:

    ExecutorService pool = Executors.newCachedThreadPool();
    

    newCachedThreadPool() 具体实现:

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

    可以看到 corePoolSize 为 0,maximumPoolSize 为 Integer.MAX_VALUE,证明这种线程池没有核心线程,但是有多个非核心线程。

    这种线程池的特点就是,当有任务提交时,如果有空闲线程则复用空闲线程,没有的话就新建线程处理。

    空闲线程如果超过 60 秒就会被回收。

    具体使用如下:

    ExecutorService pool = Executors.newCachedThreadPool();
    
    Runnable task = new Runnable() {
         @Override
          public void run() {
              System.out.println("haha");  
          }
    };
    
    pool.execute(task);
    

    3.4 SingleThreadExecutor

    一种只有一个工作线程的线程池。

    可以通过 Executors 的 newSingleThreadExecutor() 方法创建:

    ExecutorService pool = Executors.newSingleThreadExecutor();
    

    newSingleThreadExecutor() 具体实现:

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

    从源码可以看出,这种线程池只有一个核心线程,并且总线程数为 1。

    具体使用如下:

    ExecutorService pool = Executors.newSingleThreadExecutor();
    
    Runnable task = new Runnable() {
         @Override
          public void run() {
              System.out.println("haha");  
          }
    };
    
    pool.execute(task);
    

    3.5 ScheduledThreadPool

    一种核心线程数量固定,非核心线程数不固定的线程池。

    可以通过 Executors 的 newScheduledThreadPool() 方法创建:

    ExecutorService pool = Executors.newScheduledThreadPool(4);
    

    newScheduledThreadPool() 具体实现:

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
    // DEFAULT_KEEPALIVE_MILLIS = 10L
    public ScheduledThreadPoolExecutor(int corePoolSize) {
         super(corePoolSize, Integer.MAX_VALUE,
                  DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
                  new DelayedWorkQueue());
    }
    
    // 进去 super 的代码
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue) {
          this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
    }
    

    从源码可以看出这种线程池的核心线程是固定的,非核心线程数没有限制,但是非核心线程出现空闲后,10 毫秒就会被回收。

    具体使用:

    ExecutorService pool = Executors.newFixedThreadPool(4);
    
    Runnable task = new Runnable() {
         @Override
          public void run() {
              System.out.println("haha");  
          }
    };
    
    // 1 秒后执行任务
    pool.schedule(task, 1, TimeUnit.SECONDS);
    
    // 延迟 10 毫秒后,每隔 2000 毫秒执行一次任务
    pool.scheduleAtFixedRate(task, 10,2000, TimeUnit.MICROSECONDS);
    

    相关文章

      网友评论

        本文标题:什么是线程池?为什么要使用线程池?如何使用?

        本文链接:https://www.haomeiwen.com/subject/lldmshtx.html