线程池

2022-12-03  本文已影响0人  小鱼_a563

1.为什么要使用线程池?2.线程池的基本原理是什么?3.怎么学习线程池?
线程池使用了池化技术。池化技术用于我们常见的:数据库连接池,jvm中的常量池,对象池,线程池等等
池化技术:通俗的意思就是将一些我们经常用的资源预先放入一个池子中,后面我们需要使用资源的时候不需要再次创建,使用完毕之后也不需要销毁资源,只需要重新放回到池子中。因为很多大型并且常用的资源创建和销毁都是极具消耗内存和CPU的。
线程池优点

了解线程池的三大方法,七大参数,四种拒绝策略

三大方法

三大方法指的是创建线程池的三种方式(不推荐使用,因为容易导致oom。我们开放一般会使用ThreadPoolExecutor创建线程池)。

/**
 * @author 小鱼
 * @version 1.0
 * @date 2022/12/3 11:39 上午
 *  三大方法:
 *    1.Executors.newSingleThreadExecutor()
 *      使用Executors创建一个线程池,线程池中只有一个线程
 *    2.Executors.newCachedThreadPool()
 *      使用Executors创建一个线程池,遇强则强,遇弱则弱。一个弹性的线程池,会根据提交的任务数自动改变池中的线程数量
 *    3.Executors.newFixedThreadPool(int nThreads)
 *      使用Executors创建一个固定大小的线程池,参数是线程个数。
 */
public class Demo01 {
  public static void main(String[] args) {
    ExecutorService threadPool = Executors.newSingleThreadExecutor();
//    ExecutorService executorService = Executors.newCachedThreadPool();
//    ExecutorService executorService = Executors.newFixedThreadPool(5);
    try {
      for (int i = 0; i < 10; i++) {
        threadPool.execute(()->{
          System.out.println(Thread.currentThread().getName() + " OK");
        });
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      threadPool.shutdown();
    }
  }
}
SingleThreadExecutor.png
CachedThreadPool.png
FixedThreadPool.png

七大参数

七大参数说的是ThreadPoolExecutor类中的七个参数,重点:核心线程数,拒绝策略
下面也会通过一个银行办理业务的列子详细的介绍这七个参数作用。
上面的三大方法中创建线程池其实内部实现还是调用了ThreadPoolExecutor类。
比如:newFixedThreadPool(int nThreads)方法。

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

下面看一下ThreadPoolExecutor中怎么创建线程池的,并且7个参数有什么含义。

参数名 含义
corePoolSize 池中核心线程数量,也可以理解为保留的数量
maximumPoolSize 池中线程最大的数量
keepAliveTime 当任务超过了核心线程数量,多久超时了之后,开启池中其他空闲线程
unit 超时单位
workQueue 阻塞队列,当提交任务超过核心线程数量时,任务就会放入阻塞队列中
threadFactory 创建线程池,一般使用默认的
handler 拒绝策略,任务数量超过了池子最大处理范围,就会通过拒绝策略进行拒绝任务
 public class Demo02 {

  public static void main(String[] args) {
    ThreadPoolExecutor threadPoolExecutor = null;
    try {
      threadPoolExecutor = new ThreadPoolExecutor(
          2,
          5,
          3,
          TimeUnit.SECONDS,
          new LinkedBlockingQueue<Runnable>(3),
          Executors.defaultThreadFactory(),
          new ThreadPoolExecutor.AbortPolicy()
      );
      for (int i = 1; i <= 8; i++) {
        threadPoolExecutor.execute(()->{
          System.out.println(Thread.currentThread().getName() + " OK");
        });
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      threadPoolExecutor.shutdown();
    }
  }
}

四大拒绝策略

当任务数量超过线程池中最大处理范围,就会由线程池的拒绝策略处理任务

拒绝策略名称 具体含义
AbortPolicy() 多出的任务直接拒绝处理导致丢失任务),直接抛出异常:java.util.concurrent.RejectedExecutionException
CallerRunsPolicy() 多出来的任务,哪里来的回哪里去,线程池也不处理,不会抛出异常(见图:CallerRunsPolicy.png)
DiscardPolicy() 多出的任务直接拒绝处理,不抛出异常(导致丢失任务)。
DiscardOldestPolicy() 多出的任务池子会去尝试的竞争最早处理任务的线程A,如果最早线程A还在处理任务,就直接拒绝任务。如果线程A没有处理任务,那么线程A会继续执行未处理的任务。不抛出异常。
CallerRunsPolicy.png

银行业务办理列子

下面我们通过一个银行排队处理业务的列子深入理解一下这七大参数

怎么设置核心和最大的线程数

1.CPU型:cpu有几个线程就设置几个(Runtime.getRuntime().availableProcessors())
2.IO密集型:开放人员知道自己系统有多少个大IO操作任务,然后一般都是根据这个数量*2

上一篇 下一篇

猜你喜欢

热点阅读