线程和线程池

线程是程序执行的最小单位,存在于进程中,多线程允许并发执行任务。线程池通过管理线程资源,减少内存消耗,常用的有FixedThreadPool、SingleThreadPool等。线程安全问题主要源于资源竞争,通过同步代码块解决。线程池的参数如corePoolSize、maximumPoolSize等影响任务调度策略。
摘要由CSDN通过智能技术生成

线程是什么,线程和进程的区别是什么

线程,程序执行流的最小执行单位。是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

线程的生命周期在这里插入图片描述


单线程和多线程

单线程:只有一条线程在执行任务;
多线程:创建多条线程同时执行任务。

并行和并发

  1. 并行
    同一时间段内多个任务一起执行,由于CPU的运算速度非常快,任务的交替执行在我们看来是同时执行。
  2. 并发
    真正意义上的同时执行多个任务,通过多核CPU,多个任务可在同一时刻一起执行。

多线程的安全问题

多个线程同时执行一个任务时,它们会共享同一份资源,由于线程CPU的资源可能被任何一个线程抢占,当第一条线程先抢占到CPU资源,它进行了一个操作,此时第二条线程抢占到了CPU资源,而共享资源还来不及变化,就有两条线程中的数据使用了同一资源,具体可参考多线程买票问题。这个问题应该如何解决呢?
这个问题主要的矛盾在于,CPU的使用权抢占和资源的共享发生了冲突,解决时,我们只需要让一条线程抢占了CPU资源时,阻止第二条线程抢占CPU的执行权,在代码中,只需要在方法中使用同步代码块即可。
详细参考:https://blog.csdn.net/weimeig/article/details/79512965

线程池

在一个应用程序中,我们可能需要多次创建并销毁线程,而创建并销毁线程的过程势必会消耗内存。在Java中,内存资源是极其宝贵的,所以,我们提出了线程池的概念。

线程池:
Java中开辟出了一种管理线程的概念,这个概念叫做线程池。从概念及应用场景可看出,线程池的好处就是可以方便的管理线程,并减少内存的消耗。
Java中提供了创建线程池的一个类:Executor,而我们创建时,一般使用其子类:ThreadPoolExecutor

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,  
                          int maximumPoolSize,  
                          long keepAliveTime,  
                          TimeUnit unit,  
                          BlockingQueue<Runnable> workQueue,  
                          ThreadFactory threadFactory,  
                          RejectedExecutionHandler handler)

这是其中最重要的一个构造方法,它决定了创建出来的线程池的各种属性,用两张图来直观地理解线程池和这几个参数:
在这里插入图片描述
可看出,线程池中的corePoolSize就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收;maximumPoolSize就是线程池中可以容纳的最大线程的数量;keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间;unit,就是计算这个时间的一个单位;workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出);threadFactory,就是创建线程的线程工厂;handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。

corePoolSize,maximumPoolSize,workQueue之间的关系:

  • 当线程池中线程数小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
  • 当线程池中线程数达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 。
  • 当workQueue已满,且maximumPoolSize > corePoolSize时,新提交任务会创建新线程执行任务。
  • 当workQueue已满,且提交任务数超过maximumPoolSize,任务由RejectedExecutionHandler处理。
  • 当线程池中线程数超过corePoolSize,且超过这部分的空闲时间达到keepAliveTime时,回收这些线程。
  • 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize范围内的线程空闲时间达到keepAliveTime也将回收。

线程池的执行流程

在这里插入图片描述
在这里插入图片描述
任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。

handler的拒绝策略

四种:

  • AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满;
  • DisCardPolicy:不执行新任务,也不抛出异常;
  • DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行;
  • CallerRunsPolicy:直接调用execute来执行当前任务

常见的线程池

  • CachedThreadPool
    可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
  • SecudleThreadPool
    周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
  • SingleThreadPool
    只有一条线程来执行任务,适用于有顺序的任务的应用场景。
  • FixedThreadPool
    定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值