• 一篇文章让你搞懂线程


    1. 线程与进程

    1.1 概念

    进程:资源分配的基本单元,如QQ音乐

    线程:资源调度的基本单元,如QQ音乐中的播放功能

    1.2 区别与联系

    ①联系:

    线程包含在进程里面,多个线程共享一个进程的内存空间;
    进程之间是相互独立的,所以进程之间想要互相通信就得借助一些手段才可以;

    ②区别: 回答点——>地址空间、开销、并发性、内存、健壮性
    进程和线程的主要差别在于它们是不同的操作系统资源管理方式。

    地址空间

    • 进程之间各自独立,而多个线程之间是共享进程的地址空间;
    • 线程有自己堆栈和局部变量;

    开销

    • 进程的上下文切换时间开销消耗资源大,效率差;
    • 线程由于共享一个地址空间,所以线程之间的切换非常快;

    并发性

    • 进程的并发性低;
    • 线程的并发性高;

    内存:

    • 系统在运行的时候会为每个进程分配不同的内存空间;
    • 而对线程而言,除了 CPU 外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源;

    健壮性

    • 一个进程崩溃后,在保护模式下不会对其他进程产生影响;
    • 但是一个线程崩溃整个进程都会死掉。所以多进程要比多线程健壮;

    其他:

    • 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口
    • 但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制;

    2. 线程的5种状态和切换

    线程的生命周期一共分为五个部分,分别是:新建,就绪,运行,阻塞,死亡

    2.1 简单介绍

    • 新建状态(New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()
    • 就绪状态(Runnable): 此时线程正在就绪队列中排队等候得到CPU资源;(线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。)处于就绪状态的线程,随时可能被CPU调度执行。
    • 运行状态(Running): 线程获得CPU资源正在执行,此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。需要注意的是,线程只能从就绪状态进入到运行状态。
    • 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程重新进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:线程阻塞态的具体分类
      • (01) 等待阻塞 – 通过调用线程的wait()方法,让线程等待某工作的完成;
      • (02) 同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
      • (03) 其他阻塞 – 通过调用线程的sleep()join()发出了I/O请求时,线程会进入到阻塞状态;
        sleep()状态超时join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态
    • 死亡状态(Dead): 当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
      • ​ 自然终止:正常运行run()方法后终止
      • ​ 异常终止:调用stop()方法让一个线程终止运行,该线程结束生命周期。

    2.2 状态切换

    在这里插入图片描述注意:线程只能从就绪态运行态

    2.2.1 重点情况

    运行——>阻塞

    • 调用wait()方法,等待某事件发生(等待阻塞);
    • 获取synchronized锁失败,(被其他线程正在使用)(同步阻塞);
    • 发生I/O请求(等待用户输入)、调用sleep()或join()方法(其他阻塞)

    阻塞——>就绪

    • sleep()、join()等待线程终止或者超时;
    • I/O处理完毕时,线程重新转入就绪状态。

    3. 线程中常见的方法

    请大家看这篇博客:线程中常见的方法

    4. 线程池

    • 概念:一种多线程的处理形式,管理多个线程;

    • 主要思想:在进程开始时创建一定数量的线程,并加到池中以等待工作。当服务器收到请求时,它会唤醒池内的一个线程(如果有可用线程),并将需要服务的请求传递给它。一旦线程完成了服务,它会返回到池中再等待工作。如果池内没有可用线程,那么服务器会等待,直到有空线程为止。

    • 目的减少资源的消耗,提高对资源的利用率

      解释
      java线程的创建非常昂贵,需要JVM和OS(操作系统)互相配合完成大量的工作。而java高并发频繁的创建和销毁线程的操作是非常低效的,如何降低java线程的创建成本,就必须要使用到线程池。

    • 使用线程池的优点

      • 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
      • 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
      • 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
    • 线程池的七个参数

      • corePoolSize:核心线程数,线程池正常情况下保持的线程数,大户人家“长工”的数量
      • maximumPoolSize:最大线程数,当线程池繁忙时最多可以拥有的线程数,大户人家“长工”+“短工”的总数量。
      • keepAliveTime:空闲线程存活时间,没有活之后“短工”可以生存的最大时间。
      • TimeUnit:时间单位,配合参数 3 一起使用,用于描述参数 3 的时间单位。
      • BlockingQueue:线程池的任务队列,用于保存线程池待执行任务的容器。
      • ThreadFactory:线程工厂,用于创建线程池中线程的工厂方法,通过它可以设置线程的命名规则、优先级和线程类型。
      • RejectedExecutionHandler:拒绝策略,当任务量超过线程池可以保存的最大任务数时,执行的策略。

    参考博客:线程池详解:线程池概念以及架构 (baidu.com)

  • 相关阅读:
    Excel自学三部曲_Part3:Excel工作场景分析实战
    自动化之RPA工具之UiBot
    [msyql]实战:关于回表的一次查询优化实战
    Unity-GameFramework-202208最新踩坑记录(未完待续...不断完善中...)
    FLUME 安装配置及使用示例
    Java虚拟机内存模型
    Docker最基本使用
    自制操作系统日志——第二十天
    【数据结构】二叉搜索树
    京东前端经典react面试题合集
  • 原文地址:https://blog.csdn.net/m0_48904153/article/details/126515327