线程池

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

  • 线程池解决了线程的创建销毁的资源浪费的问题 。
  • 便于管理线程。
  • 提高线程的响应速度。

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

三大方法

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

  • Executors.newSingleThreadExecutor():使用Executors创建一个线程池,线程池中只有一个线程(结果看下图:SingleThreadExecutor.png)
  • Executors.newCachedThreadPool(): 使用Executors创建一个线程池,遇强则强,遇弱则弱。一个弹性的线程池,jvm会根据提交的任务数自动改变池中的线程数量(结果看下图:CachedThreadPool.png)
  • Executors.newFixedThreadPool(int nThreads):使用Executors创建一个固定大小的线程池,参数是线程个数。(结果看下图:FixedThreadPool.png)
/**
 * @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

银行业务办理列子

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

  • 场景:生活中,人们经常去银行办理业务,常见的是银行总共有5个窗口(最大线程数量),3个休息等待区(阻塞队列),一直开放的窗口有2个(核心线程数量),当人比较多的时候,休息区也满了还有人要办理业务的时候另外3个也会开放(任务等待超时了,空闲的线程去处理任务)。人员太多了,业务员处理到加班也处理不完,银行保安可能就告诉后面的人不用排队了,或者直接关门(拒绝策略)


    场景一.png

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容