第一章JUC概述

news2025/2/9 6:25:44

文章目录

  • 什么是JUC
  • 为什么学习好多线程很重要
    • 硬件来说
    • 软件来说
    • 存在的问题
  • Java多线程相关概念
    • 一把锁
    • 两个并
    • 三个程
      • 进程和程序的联系
      • 线程和进程的联系
      • 管程
  • 用户线程和守护线程
  • JAVA线程

什么是JUC

在 Java 5.0 提供了 java.util.concurrent ( 简称JUC ) 包, 在此包中增加了在并发编程中很常用的实用工具类, 用于定义类似于线程的自定义子系统, 包括线程池、 异步 IO 和轻量级任务框架。提供可调的、 灵活的线程池。 还提供了设计用于多线程上下文中的 Collection 实现等

  • 涉及到的内容
    • java.util.concurrent
    • java.util.concurrent.atomic
    • java.util.concurrent.locks

为什么学习好多线程很重要

硬件来说

  • 摩尔定律从2003年开始CPU的主频不在翻倍,而是采用多核而不是更快的主频,也就是摩尔定律的失效
  • 在主频不再翻倍提高而核数不断增加的情况下,想让程序更快就必须用到并行或者并发技术

软件来说

  • 面试必备
  • 充分利用多核处理器
  • 提高程序性能,高并发系统
  • 提高程序吞吐量,异步加回调等生产需求

存在的问题

  • 线程安全性问题
  • 线程锁问题
  • 线程性能问题

Java多线程相关概念

一把锁

  • synchronized在后面讲解

两个并

并发与并行

拿餐厅吃饭举例子,餐厅来了三个客人,有这些菜的需求

img

  • 串行:就是这个餐厅只有一个厨师,想要满足3个客人的要求,只能一道一道的去做菜,先满足完你的三道菜的需求,才能去满足我的三道菜的需求。这种按顺序一道一道满足的模式就是串行处理方式
  • 并行:这个餐厅有三个厨师,每个厨师去服务自己的客户,这样就是同时满足三个客户的需求,这种处理模式就是并行处理方式
  • 并发:餐厅还是只有一个厨师,但是我给其中一个客户做了一道菜,然后就转向给另一个用户做菜,按照一种时间片的概念去处理,每个时间片可能处理的事情是不一样的

如果厨师做菜的速度非常快,1分钟就能出一道菜,那么我上了一道菜,然后过了3分钟又出了一道菜,那么在现实生活中,我们就会感觉这个厨师就是专门在为我们服务,将这种思想用到计算机中,我们知道CPU的处理速度是非常快的,基本是以ns为单位的处理速度,所以在CPU在并发的执行计算机任务,在我们主观的意识中,我们就感觉这个CPU是在并行的处理任务

三个程

进程、线程、管程

进程和程序的联系

什么是程序

  • 程序就是一系列有组织的文件,封装操作系统的各种API,实现不同的效果(程序就是指令序列,程序的代码放入程序段中,输出和输入的数据放入数据段中),比如QQ就是一个程序

什么是进程

  • 进程就是程序执行的一次执行过程,是系统进行资源分配的一个独立最小单位(资源指CPU,内存等关键系统资源)
  • 比如我登录了两次QQ,那么我在后台任务管理器,出现了两次QQ的进程,每个进程都是QQ执行的一次过程

img

为何引入进程

  • 因为当代操作系统都是具有多道程序技术实现并发处理,在内存中会放入多个程序,那么会存在多个程序段和数据段,操作系统如何正确找到对应的程序和数据段,所以引入了进程的概念(为了使程序可以并发的执行,并且可以对并发执行的程序加以描述和控制)

进程和程序的区别

  • 进程是动态的,程序是静态的

  • 进程可以并发执行,但是程序不可以

  • 二者无一一对应的关系

  • 进程与程序又有密切的联系: 进程不能脱离具体程序而虚设, 程序规定了相应进程所要完成的动作。

  • 组成不同。进程包含PCB、程序段、数据段。程序包含数据和指令代码。

  • 程序是一个包含了所有指令和数据的静态实体。本身除占用磁盘的存储空间外,并不占用系统如CPU、内存等运行资源。

  • 进程由程序段、数据段和PCB构成,会占用系统如CPU、内存等运行资源。

  • 一个程序可以启动多个进程来共同完成。

例子

img

进程调度算法

  • 先来先服务调度算法(FCFS)
  • 短作业(进程)优先调度算法
  • 高优先权优先调度算法 1非抢占式优先权算法 2抢占式优先权调度算法 3高响应比优先调度算法
    • 高响应调度算法的优先级的计算

img

线程和进程的联系

什么是线程

  • 现代操作系统都是多线程操作系统,线程就是进程的一个子任务,进程就是轻量级的进程
  • 我们打开的浏览器这个进程,然后每打开的一个网页都是独立的线程,每个线程都可以执行一个子任务

img

为什么引入线程

  • 有些进程可能需要“同时”做很多事,但是传统的进程只能串行得与执行一系列程序(比如你在使用QQ时,你登陆了账号,相当于创建了一个进程,你可以一边打字,一边视频聊天,这些是“同时”进行的,但是传统的进程是不能实现这样的功能,所以引入线程,加快并发的速度)
  • 如果说在OS中引入进程的目的是为了使多个程序能够并发执行,比提高资源利用率和系统吞吐量,那么在OS中引入线程,是为了减少程序在并发执行时所付出的时间和空间开销,让OS具有更好的并发性(让进程并发得完成多种功能)
  • 引入了线程之后,进程是除CPU之外系统资源的分配单元,如打印机,内存空间都是分配给进程的
  • 引入了线程之后,不仅程序能够并发执行了,进程也能并发执行了,从而提高了系统并发度

img

线程和进程的比较

  • 进程是OS资源分配的基本单位,线程是调度的基本单位

  • 创建和消耗进程的开销远远比创建和消耗线程大的多,调度一个线程比进程快的多

  • 进程包含线程,每个进程至少包含一个线程(主线程)

  • 进程之间相互独立,不同的进程不会共享内存空间,但是同一个进程的线程会共享内存空间(共享进程的资源),线程几乎不拥有系统资源

  • 在多CPU操作系统中,不同的线程可以去占用不同的CPU

  • 同一进程的线程切换不会导致进程切换,但是不同进程的线程切换,会导致进程的切换

线程的优点

  1. 创建一个新线程的代价要比创建一个新进程小得多

  2. 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多

  3. 线程占用的资源要比进程少很多

  4. 能充分利用多处理器的可并行数量,能够发挥多核CPU的优势

  5. 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务

  6. 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现

管程

  • 也就是Monitor(监视器),也就是平时所说的锁
  • Monitor其实是一种同步机制,它的义务是保证(同一时间只有一个线程可以访问被保护的数据和代码)

为什么引入管程?

在这里插入图片描述

  • 虽然我们的记录型信号量能够真正的实现临界区的四大条件**(空闲让进 忙则等待 有限等待 让权等待 )** 但是在上面的例子中,我们知道消费者和生产者问题中,如果P的顺序反了(实现互斥的P操作一定要在实现同步的P操作之后),就会导致死锁的问题,PV操作编写困难,容易出错
    • mutex为了实现缓冲区互斥
    • empty是为了缓存区数量实现同步操作
  • 所以提出了管程这种概念,这是一种高级同步机制

管程的组成及基本特征

组成

  • 局部于管程的共享数据结构
  • 对该数据结构进行操作的一组过程 (过程当成函数 管程当作类 共享数据结构当作类里面的属性)
  • 对局部于管程的共享数据设置初始值的语句
  • 管程有一个名字

基本特征

  • 局部于管程的数据只能被局部于管程的过程所访问(封装思想)
  • 一个进程只有通过调用管程内的过程才能进入管程访问共享数据
  • 每次仅允许一个进程在管程内执行某个内部过程(实现了互斥访问)

管程实现生产者消费者问题

在这里插入图片描述

  • 对于资源的互斥操作由编译器负责实现各进程互斥进入管程中的过程来实现
  • 但是生产者和消费者的模型中还需要实现同步关系,我们需要用wait和signal来实现同步我们的full和empty有着对应的阻塞队列

Java中类似于管程的机制

1

public class startTest {
    public static void main(String[] args) {
        Object o=new Object();
        new Thread(()->{
            synchronized (o){

            }
        },"t2").start();
    }
}
  • JVM中同步是基于进入和退出监视器对象(Monitor,管程对象)来实现的,每个对象实例都会有一个Monitor对象
  • Monitor对象会和Java对象一同创建并销毁,它底层是由C++语言来实现的。
  • 执行线程就要要求先成功持有管程,然后才能执行方法,最后当方法完成时释放管程,在方法执行的期间线程拥有了管程,其他线程都无法再获取到同一个管程

用户线程和守护线程

Java线程分为用户线程和守护线程

  • 一般情况下不做特别说明配置,默认都是用户线程

  • 用户 (User) 线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程

  • 守护 (Daemon) 线程:运行在后台,为其他前台线程服务。也可以说守护线程是 JVM 中非守护线程的 “佣人”

    • GC垃圾回收线程就是经典的守护线程
    • 一旦所有用户线程都结束运行,守护线程会随 JVM 一起结束工作
  • 线程的daemon属性为

    • true表示是守护线程
    • false表示是用户线程。
public class DaemonDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName()+"\t 开始运行,"
                    +(Thread.currentThread().isDaemon() ? "守护线程":"用户线程"));
            while (true){

            }
        },"t1");
        //线程的daemon属性为true表示是守护线程,false表示是用户线程
        //---------------------------------------------
        t1.setDaemon(true);
        t1.start();
        //3秒后主线程再运行
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("----------main线程运行完毕");
    }
}

两种情况

  1. 未加t1.setDaemon(true);,默认是用户线程,t1继续运行,所以灯亮着
  2. 加了t1.setDaemon(true);是守护线程,当用户线程main方法结束后t1自动退出了

守护线程作为一个服务线程,没有服务对象就没有必要继续运行了,如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可退出了。假如当系统只剩下守护线程的时候,Java虚拟机会自动退出。

setDaemon(true)方法必须在start()之前设置,否则报IIIegalThreadStateException异常

JAVA线程

Java 主类名称 启动的是JAVA进程
类中的主方法是这个类的主线程 ,线程是操作系统中的概念 . 操作系统内核实现了线程这样的机制 , 并且对用户层提供了一些 API 供用户使 用( 例如 Linux 的 pthread 库 ). Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装

img

什么叫多线程

多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。

上下文切换:

  • 多线程编程中一般线程的个数都大于 CPU 核心的个数,而一个 CPU 核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效执行,就会使用一些策略让线程轮流使用CPU,上下⽂切换(有时也称做进程切换或任务切换)是指 CPU 从⼀个进程(或线程)切换到另⼀个进程(或线程)。上下⽂是指某⼀时间点 CPU 寄存器和程序计数器的内容,也就是线程(进程)执行的环境

举例说明 线程A - B

  • 1.先挂起线程A,将其在cpu中的状态保存在内存中。
  • 2.在内存中检索下⼀个线程B的上下⽂并将其在 CPU 的寄存器中恢复,执⾏B线程。
  • 3.当B执⾏完,根据程序计数器中指向的位置恢复线程A。

Java 中用到的线程调度算法(Java实现的是抢占式,Java是由JVM中的线程计数器来实现线程调度)

分时调度模型和抢占式调度模型。

  • 分时调度模型是指让所有的线程轮流获得 cpu 的使用权,并且平均分配每个线程占用的 CPU的时间片这个也比较好理解。
  • Java 使用的线程调使用抢占式调度, Java 中线程会按优先级分配 CPU 时间片运行, 且优先级越高越优先执行,但优先级高并不代表能独自占用执行时间片,可能是优先级高得到越多的执行时间片,反之,优先级低的分到的执行时间少但不会分配不到执行时间。

线程让出 cpu 的情况

  1. 当前运行线程主动放弃 CPU, JVM 暂时放弃 CPU 操作(基于时间片轮转调度的 JVM 操作系统不会让线程永久放弃 CPU,或者说放弃本次时间片的执行权),例如调用 yield()方法。
  2. 当前运行线程因为某些原因进入阻塞状态,例如阻塞在 I/O 上。
  3. 当前运行线程结束,即运行完 run()方法里面的任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/640534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Cloud Alibaba - Sentinel源码分析

目录 一、Sentinel核心源码分析 1、Sentinel核心概念 1.1、Node之间的关系 2、Sentinel源码入口 2.1、SlotChain解析 2.2、NodeSelectorSlot解析 2.3、ClusterBuilderSlot解析 一、Sentinel核心源码分析 Sentinel是分布式系统的防御系统。以流量为切入点,通过…

001安装Jenkins

安装JenkinsJenkins 是一个开源自动化服务器http://www.jenkins.io/zh/doc/book/installing/#%E7%B3%BB%E7%BB%9F%E8%A6%81%E6%B1%82 docker docker run \-u root \--rm \-d \-p 8080:8080 \-p 50000:50000 \-v jenkins-data:/var/jenkins_home \-v /var/run/docker.sock:/va…

传感器融合概念及对比

1.多传感器融合的定义 传感器数据融合的定义可以概括为把分布在不同位置的多个同类或不同类传感器所提供的局部数据资源加以综合,采用计算机技术对其进行分析,消除多传感器信息之间可能存在的冗余和矛盾,加以互补,降低其不确实性…

记录好项目D2

记录好项目 你好呀,这里是我专门记录一下从某些地方收集起来的项目,对项目修改,进行添砖加瓦,变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个旅游门户网站 技术栈:JSPjQueryAjaxechartsSpringSpring…

第四章LockSupport与线程中断

文章目录 线程中断机制面试题什么是中断机制?实现三种中断方式通过一个volatile变量实现通过AtomicBoolean(原子布尔型)通过Thread类自带的中断api方法实现 API源码分析当前线程的中断标识为true,是不是线程就立刻停止?后手案例-…

Vector-常用CAN工具 - Vector Hardware Manager

本文提供了有关 Vector 用于配置 Vector 接口的新工具Vector 硬件管理器(vHardwareManager) 的一些一般信息。 常见问题 1、什么是vHardwareManager? 2、哪些接口支持vHardwareManager? 3、什么时候需要vHardwareManager? 4、哪里可以下…

chatgpt赋能python:Python如何截图运行效果?

Python如何截图运行效果? 如果你是一位有10年python编程经验的工程师,那么你一定知道在编写程序时调试和调整非常重要。为了更好地调试程序,Python提供了许多进行程序运行效果截图的方法。本文将介绍几种常用的Python截图方法以及它们的优缺…

chatgpt赋能python:Python如何截图运行结果

Python如何截图运行结果 介绍 Python是一种高级编程语言,非常流行。它具有许多有用的功能和库,使其成为许多开发人员的首选编程语言之一。但是,当您运行Python程序并需要与他人共享结果时,您可能需要截图运行结果。在本文中&…

编译3D渲染引擎Horde3D

Horde3D是Github上一款开源的轻量级3D渲染引擎,同时它还支持多个平台。今天我们准备在Mac平台上交叉编译至Android平台。如果需要同时能编译Sample,那么还需要SDL2库。默认情况下,编译Horde3D时不强制下载SDL2,你可以选择强制下载…

chatgpt赋能python:Python怎么快速入门?

Python怎么快速入门? Python是一种易学易用的编程语言。它被广泛应用于各种领域,例如数据科学、自动化、Web开发、游戏开发等等。无论你是从事什么领域,在Python的快速入门上花费越少的时间越好。在本文中,我们将介绍Python的基础…

工作二--注意!!!

1、激活单元格,做数据回显 2、单元格退出编辑模式时,让 实时保存 3、获取数据时,用getGIUID 给数据 唯一id,以防数据名重复 数据结构:是结合接口的id 等 和 组件的数据结构 4、父子结构 下拉框中的 :value 把value值 …

网络安全如何6个月成功上岸?

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了. 2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发. 3.有时多 google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答. 4.遇到实在搞不懂的,可以先放放,以后再来解…

Haproxy搭建Web高可用群集 【Keepalived+HAProxy 高可用 日志定义 内核优化】

Haproxy HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,是免费、快速并且可靠的一种解决方案。HAProxy非常适用于并发大(并发达1w以上)web站点,这些站点通常又需要会话保持或七层处理。HAProxy的运行模式使得它可…

Oracle 查询优化改写(第一章)

第一章 单表查询 1.查询空值 2.将空值转换为实际值 不采用nvl()函数,而使用COALESCE函数语法为COALESCE(表达式1,表达式2,...,表达式n),n>2,此表达式的功能为返回第一个不为空的表达式,如果都为空则返回空值。 注…

每日算法总结——回溯算法、 LeetCode 131. 分割回文串

LeetCode 131. 分割回文串 131. 分割回文串 - 力扣(LeetCode) 什么是回溯算法? 回溯算法真的是解决排列问题的一大利器,其实很多时候自己不经意间就写出了回溯算法,但是一直没有一个系统的认识,今天做一…

B树:数据结构中的平衡之道

目录 引言:一、定义:二、特点:三、应用场景:总结: 引言: 在计算机科学领域中,数据结构是构建和组织数据的重要工具。其中,B树(B-tree)作为一种自平衡的搜索树…

用RDMA重新思考有状态流处理

摘要 远程直接内存访问 (RDMA) 硬件弥合了网络和主要内存速度之间的差距,从而验证了网络通常是分布式数据处理系统中的瓶颈的常见假设。然而,高速网络并没有提供“即插即用”的性能(例如,使用 IP-overInfiniBand)&…

第二章 数据处理篇:transforms

教程参考: https://pytorch.org/tutorials/ https://github.com/TingsongYu/PyTorch_Tutorial https://github.com/yunjey/pytorch-tutorial 详细的transform的使用样例可以参考:ILLUSTRATION OF TRANSFORMS 文章目录 为什么要使用transformstransforms方…

RK3588平台开发系列讲解(以太网篇)PHY驱动

文章目录 一、PHY驱动初始化二、PHY 配置初始化三、PHY 的扫描四、PHY 的STATUS状态读取五、PHY的RESET 复位六、PHY 的注册phy_device_register七、PHY 的状态变化沉淀、分享、成长,让自己和他人都能有所收获!😄 一、PHY驱动初始化 完成了mdio总线的注册,以及对不一样厂家…

chatgpt赋能python:Python怎么截图

Python怎么截图 介绍 在日常的工作和学习中,截图是一项非常常见的操作。随着Python在各个领域的不断普及和应用,使用Python进行截图也成为了一个热门话题。Python作为一种高级编程语言,具备丰富的第三方库和模块,可以实现复杂的…