美文网首页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);

相关文章

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

  • 线程池

    线程池 [TOC] 线程池概述 什么是线程池 为什么使用线程池 线程池的优势第一:降低资源消耗。通过重复利用已创建...

  • 八、线程池剖析

    一、前置问题 线程的状态转换 为什么要使用线程池 线程池的继承体系 线程池使用的场景 线程数的设置规则 线程池的状...

  • Java线程池的原理及几类线程池的介绍

    在什么情况下使用线程池? 使用线程池的好处: 线程池工作原理:为什么要用线程池? 诸如 Web 服务器、数据库服务...

  • 线程池

    线程池有哪些?区别是什么?为什么要使用线程池? 简介 线程池,是多线程中一种线程使用模式。为解决短时任务的性能消耗...

  • 线程池概述

    为什么要使用线程池? 线程池核心参数 线程池的几种拒绝策略 execute()和submit()的区别 线程池工作...

  • 01 java线程池-初始线程池-ThreadPoolExecu

    java线程池 为什么要用线程池? 降低系统资源消耗。 提高线程可控性。 如何创建使用线程池? JDK8提供了五种...

  • 线程池

    1.为什么要使用线程池?2.线程池的基本原理是什么?3.怎么学习线程池?线程池使用了池化技术。池化技术用于我们常见...

  • juc系列-Executor框架

    什么是线程池 线程池:管理一组工作线程的资源池。 为什么使用线程池 1.避免反复创建回收线程,降低资源消耗。2.提...

  • JDK多任务执行框架

    1、为什么要使用线程池?2、线程池有什么作用?3、说说几种常见的线程池及使用场景。4、线程池都有哪几种工作队列?5...

网友评论

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

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