• 多线程&JUC


    多线程

    一.什么是多线程

    进程:是程序的基本执行实体

    理解:每一个运行的软件就是一个进程

    线程:是操做系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位

    理解:应用软件中互相独立,可以同时运行的功能

    为什么要有多线程?

    在这里插入图片描述

    有了多线程就可以让程序同时做多件事情

    可以提高程序的运行效率

    多线程的应用场景

    • 软件中的耗时操做
    • 拷贝,迁移大文件
    • 加载大量的资源文件
    • 所有的聊天软件
    • 所有的后台进程

    二.多线程的两个概念

    1.并发

    同一时刻,有多个指令在单个cpu交替执行

    2.并行

    同一时刻,有多个指令在多个cpu上同时执行

    并发和并行是有可能都在发生的

    三.线程的实现方式

    继承Thread类的方式

    • 定义一个类继承Thread
    • 重写run方法
    • 创建子类的对象,并启动线程

    在这里插入图片描述

    实现Runnable接口的方式

    • 定义一个类实现Runnable接口
    • 重写里面的run方法
    • 创建自己的类的对象
    • 创建一个Thread类对象,并开启线程

    在这里插入图片描述

    细节:getName()是Thread类中的方法,所以想要调用,则

    需要获取到当前线程的对象,然后用这个对象去调用

    利用Callable接口和Future接口的方式

    **特点:**可以获取到多线程运行的结果

    • 创建一个类MyCallable实现Callable接口
    • 重写call(是有返回值的,表示多线程运行的结果)
    • 创建MyCallable的对象(表示多线程要执行的任务)
    • 创建FutureTask的对象(管理多线程运行的结果)
    • 创建Thread类对象,并启动(表示线程)

    在这里插入图片描述

    多线程三种实现方式对比

    在这里插入图片描述

    四.常见的成员方法

    Thread类中常见的成员方法

    在这里插入图片描述

    在这里插入图片描述

    细节:

    1.如果我们没有给线程设置名字,线程也是有默认名字

    格式:Thread-x(x是序号,从0开始)

    2.如果我们要给线程设置名字,可以用set方法进行设置,也可以用构造方法进行设置

    在这里插入图片描述

    细节:

    1.当JVM虚拟机启动之后,会自动的启动多条线程,其中有一条线程就叫做main线程

    它的作用就是调用main方法,并执行里面的代码

    2.哪条线程执行到sleep(),那么哪条线程就停留对应的时间

    3.参数:时间,单位:毫秒

    在这里插入图片描述

    在计算机当中,线程的调度有两种

    第一种,抢占式调度

    所谓抢占式调度,就是多个线程在抢夺cpu的执行权

    cpu在什么时候执行哪条线程是不确定的,执行多长时间也是不确定的,体现随机性

    第二种方式,非抢占式调度

    所有的线程轮流的执行

    java中,采用的是第一种,抢占式调度

    优先级越大,线程抢到cpu的概率就越大

    优先级最低:1

    最高:10

    默认:5

    在这里插入图片描述

    在这里插入图片描述

    细节:

    当其他的非守护线程执行完毕之后,守护线程会陆续结束

    守护线程的应用场景:

    比如,聊天窗口,既可以聊天,也可以发文件

    聊天看成一个线程,发文件看成另一个线程

    此时,如果把聊天窗口关掉,那么发文件线程也就没有存在的必要了

    所以,就可以把发文件线程设置为守护线程

    在这里插入图片描述

    尽可能的让出cpu

    在这里插入图片描述

    在这里插入图片描述

    线程的生命周期

    在这里插入图片描述

    五.线程安全的问题

    买票引发的安全问题

    • 相同的票出现了多次
    • 出现了超出范围的票

    在这里插入图片描述

    在这里插入图片描述

    线程执行时,有随机性

    同步代码块

    把操做共享数据的代码锁起来

    格式:

    在这里插入图片描述

    特点:

    • 锁默认打开,有一个线程进去了,锁自动关闭
    • 里面的代码全部执行完毕,线程出来,锁自动打开

    锁对象是任意的对象,但是要保证锁对象是唯一

    static Object obj = new Object();

    同步代码块的两个细节

    • 锁对象一定是唯一的,一般用字节码文件对象:类名.class

    • synchronized一定要写在循环的里面

      说明:如果把synchronized写在了循环的外面,那么其他线程将没有机会去执行任务,任务都被线程一执行完了

    同步方法

    如果我们想把一个方法里面的所有代码都锁起来,那么就没有必要使用同步代码块了

    可以把synchronized直接加到方法上,那么这个方法就是同步方法

    格式:

    修饰符 synchronized 返回值类型 方法名(方法参数){}

    特点:

    • 同步方法是锁住方法里面的所有代码
    • 锁对象不能自己指定
      • 如果当前的方法是非静态的,它的锁对象是this,就是当前方法的调用者
      • 如果当前方法是静态的,它的锁对象是当前类的字节码文件对象

    写同步方法的技巧:

    先写同步代码块,然后把同步代码块抽取成一个方法

    lock锁

    JDK5以后提供了一个新的锁对象Lock

    它的实现比synchronized有更广泛的锁定操做

    它提供了两个方法:

    void lock():获得锁

    void unlock():释放锁

    这样就可以实现手动上锁和手动释放锁

    注意:

    Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

    ReentrantLock的构造方法:ReentrantLock(),创建一个ReentrantLock的实例

    在这里插入图片描述

    六.死锁

    就是在程序中出现了锁的嵌套

    在这里插入图片描述

    七.生产者和消费者

    又叫做等待唤醒机制

    生产者消费者模式是一个十分经典的多线程协作的模式

    我们知道多线程的执行具有随机性

    那么,现在我们学习的生产者和消费者模式就要打破这一特性,使得多个线程轮流执行

    生产者:生产数据

    消费者:消费数据

    在这里插入图片描述

    理想情况

    生产者先抢到cpu的执行权,进行生产数据,然后消费者再抢到cpu的执行权,进行消费数据

    消费者等待

    消费者先抢到cpu的执行权,这时发现没有数据,此时消费者处于等待状态,

    当消费者处于等待状态时,生产者会抢到cpu的执行权,判断是否有数据,

    如果没有,则生产数据,然后唤醒消费者,消费者进行消费数据

    在这里插入图片描述

    生产者等待

    生产者先抢到cpu的执行权,判断是否有数据,有则进行等待

    在这里插入图片描述

    在这里插入图片描述

    编写多线程代码的套路

    • 循环
    • 同步代码块
    • 判断共享数据是否到了末尾(到了末尾)
    • 判断共享数据是否到了末尾(没到末尾)

    阻塞队列方式实现等待唤醒机制

    阻塞队列好比是连接生产者和消费者之间的管道

    生产者可以把生产的数据放到管道当中

    消费者可以在管道中获取数据进而进行消费

    我们可以规定管道中最多可以放多少数据

    队列:数据在管道中,好比是排队一样,先进的数据,先出去

    阻塞:

    放数据时,放不进去,会等着,叫阻塞

    取数据时,取不到,也会等着,也叫阻塞

    阻塞队列的继承结构

    阻塞队列一共实现了4个接口

    iterable:表示阻塞队列可利用迭代器进行遍历或者增强for循环

    collection:表示阻塞队列是单列集合

    Queue:表示队列

    BlockingQueue:表示阻塞队列

    实现类:

    ArrayBlockingQueue:底层是数组,有界,创建对象时必须指定长度

    LinkedBlockingQueue:底层是链表,无界

    不是真正的无界,最大为int的最大值

    多线程的6种状态

    在这里插入图片描述

    在Java虚拟机当中,关于线程的状态,真正定义的只有6种状态,是没有定义运行状态的,

    因为,当线程抢到cpu时,那么此时虚拟机就会把当前线程交给操做系统去管理了,所以就没有定义运行状态

  • 相关阅读:
    c++ static
    在Android 上开发一个显示系统属性的APK应用
    万字长文详解目标检测算法,超大超全(2022最新)
    编程猫创作工具:新版Kitten新体验
    python中的进程与线程,使用.multiprocessing
    Element Plus中Cascader 级联选择器(选择任意一级选项 - 更改下拉框选中方式)
    Web前端:6个最佳在线跨浏览器测试工具(免费和付费)
    《程序员职场工具库》你的分析是否错漏百出 —— MECE 法则
    jenkins-pipeline语法总结(最全)
    SQL语句之in操作符
  • 原文地址:https://blog.csdn.net/qq_53798578/article/details/133603389