线程池,及7大参数,4大拒绝策略详解

一、线程池

1>引入

什么是线程

同一个进程中的多个线程之间可以并发执行,一个程序至少有一个进程,一个进程至少有一个线程

一个应用程序就是一个进程,进程就是在某种程度上相互隔离的、独立运行的程序。而线程是一个进程内部的多个运行单位。在Java中的并发机制可以这样理解,我们在使用计算机看视频的同时可以用它来打印文件,这些活动是可以同时进行的,而我们可以把线程理解为在程序中并发完成的每一件事——即线程是程序内部一个独立的运行单位。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。

多线程

在我们以往编写的程序中,都是在一个任务完成后再进行下一个项目的开发,这样下一个任务的开始必须等前一个任务的完成。而我们通过Java语言的并发机制,可以在程序中执行多个线程,每一个线程完成一个功能,所有线程并发执行,这种机制就叫做多线程。

举个例子

计算机的核心是CPU,承担全部运算任务。就像一个工厂,无时无刻在运行,设定这个工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。一个车间里,可以有很多工人。他们协同完成一个任务。线程就好比车间里的工人。一个进程可以包括多个线程。车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

2>线程池

自己手动为服务端创建线程,当服务端逻辑运行完了以后,线程就会被销毁。

这种做法会有大量的线程创建与销毁的工作,另外,线程在创建了以后,短时间内可以创建多少线程,线程之间的调度竞争等等,其实都会带来很大的问题。而大多数情况下,所有的多线程程序其实都会面临相同的问题。所以,干脆,JDK引入了一个统一的模型来解决这些共同的问题,这就是线程池。

线程池的思想是这样,创建固定数目的线程,当有任务需要在单独的线程中独立运行的时候,就从这些固定数目的线程中选择一个,在这个线程上执行。当任务执行完了,就会把线程还回去。这些线程就好像放在一个池子中的水一样,用的时候捞上来用一下,用完了就还回去。所以,给它起了一个很形象的名字,叫线程池。资源的池化是非常常见的一种使用空间缓存缓解系统瞬时压力的解决方案。

二、七大参数

corePoolSize
  • 含义:线程池的基本大小,即在没有任务需要执行的时候线程池的大小。
  • 作用:当有任务提交时,线程池会创建一个核心线程来执行任务,即使其他核心线程是空闲的。
maximumPoolSize
  • 含义:线程池允许创建的最大线程数。
  • 作用:当任务数超过核心线程数且任务队列已满时,线程池会创建新的线程来处理任务,但线程数不会超过最大线程数。
keepAliveTime
  • 含义:非核心线程的空闲时间,超过这个时间则会被回收。
  • 作用:在任务执行完毕后,线程池会保持空闲线程的时间,如果在这个时间内没有新的任务到达,那么超过这个时间的空闲线程会被终止。
unit
  • 含义:用于指定keepAliveTime的时间单位,例如,秒、毫秒等。
workQueue
  • 含义:用于保存等待执行的任务的阻塞队列。
  • 作用:当线程池中的线程数超过核心线程数时,新的任务会被放入任务队列等待执行。
threadFactory
  • 含义:用于创建新线程的工厂。
  • 作用:通过指定线程工厂,可以对线程的一些属性进行自定义设置。
handler
  • 含义:当任务太多来不及处理时,线程池通过指定的拒绝策略来处理新提交的任务。
  • 作用:常见的拒绝策略有AbortPolicy(抛出RejectedExecutionException异常)、CallerRunsPolicy(由提交任务的线程执行任务)、DiscardPolicy(直接丢弃任务)等。

三、四大拒绝策略

AbortPolicy(默认策略)

  • 策略行为: 抛出RejectedExecutionException异常。
  • 适用场景: 这是默认的拒绝策略,它会在任务无法被接受时抛出异常,通知调用者发生了拒绝。
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    timeUnit,
    workQueue,
    handler);  // 默认是AbortPolicy

CallerRunsPolicy:

  • 策略行为: 将任务交给提交任务的线程来执行。
  • 适用场景: 这个策略不会抛弃任务,而是在调用者的线程中直接执行被拒绝的任务。这样做可以降低新任务的提交速度。
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    timeUnit,
    workQueue,
    new ThreadPoolExecutor.CallerRunsPolicy());

DiscardPolicy:

  • 策略行为: 直接丢弃无法处理的任务,不做任何处理。
  • 适用场景: 这种策略会默默地抛弃掉无法处理的任务,不会抛出异常也不会执行任何额外的操作。
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    timeUnit,
    workQueue,
    new ThreadPoolExecutor.DiscardPolicy());

DiscardOldestPolicy:

  • 策略行为: 丢弃最早进入任务队列的任务,然后尝试重新提交新任务。
  • 适用场景: 这种策略会丢弃等待时间最长的任务,然后尝试将新任务提交到队列中。
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    timeUnit,
    workQueue,
    new ThreadPoolExecutor.DiscardOldestPolicy());

如果任务的重要性较高,可使用CallerRunsPolicy,以确保任务一定会被执行,尽管这可能会影响整体性能。如果对任务的执行没有特殊要求,可以使用默认的AbortPolicy。

四、五种状态

线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态。

线程池也有5种状态:Running,SHUTDOWN,STOP,TIDYING,TERMINATED。

1. RUNNING

状态说明:

线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。

状态切换:

线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态!

在ctl的初始化代码中(如下),就将它初始化为RUNNING状态,并且"任务数量"初始化为0。

privatefinalAtomicInteger ctl =newAtomicInteger(ctlOf(RUNNING, 0));

2. SHUTDOWN

状态说明:

线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。

状态切换:

调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。

3. STOP

状态说明:

线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

状态切换:

调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。

4. TIDYING

状态说明:

当所有的任务已终止,ctl记录的"任务数量"为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

状态切换:

当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。

当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

5. TERMINATED

状态说明:

线程池彻底终止,就变成TERMINATED状态。

状态切换:

线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值