线程基础

线程与进程的区别

  • 进程是程序的一次执行过程。它资源分配的单位
  • 线程程序执行的单位

并行和并发的区别

  • 单核CPU下,线程串行。(并发:多线程轮流使用一个或多个CPU)
  • 多核CPU下,每个核都可调度线程。(并行:多CPU同时执行多个线程。

创建线程的方式

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口
  4. 线程池创建线程
runnable和callable的区别
  • Runnable接口run方法没有返回值;Callable接口call方法返回值
  • Runnable接口run方法的异常只能内部消化不能上抛;Callable接口call方法允许抛出异常
线程的run()和start()的区别
  • start():用于启动线程能被调用一次
  • run():封装要被线程执行的代码,可以被调用多次
wait()和sleep()方法的区别

1.方法归属不同

  • sleep() 是Thread类的静态方法
  • wait() 是Object类的成员方法,任何对象都有

2.唤醒时机不同

  • 执行 sleep() 的线程会在等待相应毫秒后唤醒
  • wait() 可以被 notify() 唤醒

3.锁特性不同

  • wait()方法的调用必须先获取对象的;sleep()不需要
  • wait()执行完会释放对象锁;sleep()若在synchronized中执行,不释放对象锁

线程的状态与转换条件

三个线程如何顺序执行

使用线程中的join()方法解决。

t.join():等待线程运行结束。阻塞调用此方法的线程,直到t线程执行完成。

    并发安全

    Synchronized

    实现原理

    基于进入和退出Monitor对象来实现方法同步和代码块同步。

    • 方法级的同步是隐式,JVM可以通过 ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。
    • 代码块的同步是利用monitorentermonitorexit这两个字节码指令。

    底层实现

    synchronized的底层实现是依赖于Java对象头,以及Monitor对象监视器。

    Monitor监视器锁有三个重要属性:_Owner _WaitSet _EntryList

    • _owner指向持有ObjectMonitor对象的线程。
    • 当多个线程同时访问时,首先会进入 _EntryList 集合等待。
    • 当线程获取到对象的monitor 后,把monitor中的owner变量设置为当前线程,同时monitor中的计数器count加1。
    • 若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 _WaitSet集合中等待被唤醒。

    Monitor实现的锁属于重量级锁,于是有了锁升级,基于对象头(MarkWord)

    • 最轻程度的锁为偏向锁,资源总是由同一线程多次获得。偏向锁只依赖于锁对象,锁对象在64位虚拟机里由64Bit的Markword来控制,线程获取锁时,通过CAS方式将线程ID设置到对象头里的MarkWord的Thread ID中,线程ID指针在MarkWord中占用54个比特位偏向锁的标识位为101
    • 当对象进行了hash操作,那么锁就会失效,因为HashCode在MarkWord中占用31个比特位无锁的表示位为001
    • 接着被另外的线程所访问,偏向锁升级为轻量级锁,MarkWord中设置指向线程栈的lock record指针。其他线程会自旋尝试获取锁,不会阻塞。轻量级锁的标识位为000
    • 一旦线程竞争,升级为重量级锁,其他线程都会被阻塞重量级锁的标识位为010

    JMM(java内存模型)

    • JMM把内存分为两块,一块是私有线程的工作内存,一块是所有线程的共享区域(主内存)
    • 线程与线程间相互隔离,交互需通过主内存。

    Volatile关键字

    1. 保证线程间的可见性:修饰共享变量,防止编译器等优化发生,让线程对共享变量的修改对另一个线程可见。
    2. volatile禁止指令重排序:修饰共享变量会在读、写共享变量时加入不同屏障,阻止其他读写操作,从而阻止重排序。

    AQS

    全称为AbstractQueuedSynchronizer(抽象队列同步器)。它是构建锁的基础框架

    • AQS中有个属性state表示状态,0为无锁,1为有锁。
    • 还维护了一个双向队列作为FIFO队列,其他线程会进入队列等待,线程释放锁时会唤醒队列中head的元素。

    ReentrantLock(可重入锁)

    可重入锁指:调用lock()方法获取了锁后,再调用lock(),是会再阻塞的。

    ReentrantLock利用CAS+AQS队列实现。支持公平锁非公平锁

    Synchronized和Lock的区别

    • synchronized是关键字,在 jvm 中由c++实现;Lock 是接口,在 jdk 中由 java 实现。
    • synchronized退出锁时自动释放;Lock需要调用unlock方法释放
    • Lock的功能比synchronized,如公平锁。

    死锁产生的条件

    互斥,请求保持,不可剥夺、循环等待。

    (一个线程需要同时获取多把锁,容易发生死锁。)

    线程池

    线程池核心参数

    1. 核心线程数
    2. 最大线程数
    3. 生存时间(救急线程的生存时间)
    4. 时间单位
    5. 任务队列:当没有空闲核心线程时,新任务到此队列等待,队列满就会创建救急线程。(ArrayBlockingQueue 和 LinkedBlockingQueue)
    6. 线程工厂
    7. 拒绝策略:当所有线程在忙,工作队列也满,才会触发。
    • AbortPolicy:抛出异常,默认策略;
    • CallerRunsPolicy:调用者的线程来执行;
    • DiscardOldestPolicy:丢弃阻塞队列中最靠前的任务,执行当前任务;
    • DiscardPolicy:丢弃任务。

    如何确定核心线程数

    • IO密集型任务:核心线程数大小设置为2N+1
    • CPU密集型任务(或者高并发、任务执行时间短):核心线程数大小为N+1

    线程池的种类

    1. Executors.newFixedThreadPool():固定大小的线程池,核心线程数与最大线程数相等
    2. Executors.newSingleThreadExecutor():单线程化的线程池,保证任务FIFO执行
    3. Executors.newCachedThreadPool():可缓存的线程池,核心线程数为0
    4. Executors.newScheduledThreadPool():提供了“延迟”和“周期执行”功能

    不推荐用Executors创建线程池

    应该使用7个参数的ThreadPoolExecutor的方式,按需设置核心线程数和最大线程数,避免无限队列长度,规避OOM

    ThreadLocal

    ThreadLocal是解决线程安全问题的一个操作类,它为每个线程分配一个独立的内部存储空间,实现了线程内的资源共享。

    • set(value):设置值。根据当前线程对象,通过getMap()获取ThreadLocalMap
    • get():获取值。通过getEntry()获取ThreadLocalMap中的Entry对象。通过HashCode & (数组长度 - 1) 定位数组下标。
    • remove():清除值。同get()

    ThreadLocal内存泄漏

    强引用:表示一个对象处于有用且必须的状态,GC无法回收处于强引用的对象,即便出现OOM。

    User user = new User();

    弱引用:表示一个对象处于可能有用但非必须的状态。GC一旦发现弱引用,会回收相关联的对象。

    User user = new User();
    WeakReference weakRef = new WeakReference(user);

    每一个Thread维护一个ThreadLocalMap,Entry对象继承了WeakReference。其中key弱引用的ThreadLocal实例value是强引用的线程变量副本

    避免内存泄漏

    在使用ThreadLocal后主动使用remove()方法释放key、value。

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

    如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    WSL 配置文件 wsl.conf 设置

    WSL .wslconfig 小技巧 要在 WSL(Windows Subsystem for Linux)中增加内存,你需要编辑 WSL 配置文件 wsl.conf 或者直接调整虚拟机的资源限制。 文章目录WSL .wslconfig 小技巧以下是步骤: 找到或创建 .wslconfig 文件&#xff1…

    9.从零开始写LINUX内核——设置中断描述符表

    Linux 0.12 内核中断描述符表(IDT)完整实现代码以下是基于 setup 程序扩展的完整代码,包含中断描述符表(IDT)的定义、初始化及中断处理程序,可直接用于实验验证:asm/* setup.s —— 4 扇区&…

    手机实时提取SIM卡打电话的信令声音-当前现状与思考

    手机实时提取SIM卡打电话的信令声音-当前现状与思考 --纯手机-无外置配件的方案规划 上一篇:手机实时提取SIM卡打电话的信令声音-新的篇章(篇外小结与思考) 下一篇:手机实时提取SIM卡打电话的信令声音-整体解决方案规划 一、前言 我们在2024年09月的…

    【车联网kafka】常用参数及其命令总结(第八篇)

    目录 1、kafka参数 1.1 、消费者消息批次发送 1.2 、消息大小的配置(环环相扣的消息大小,调整时需要一起调整) 1.3 、消息重试发送幂等 1.4、消息提交 1.5、分区分配策略(自己看的设置) 1.6、文件存储 2、kafka命令 2.1 常用命令一览…

    基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统

    🔥作者:it毕设实战小研🔥 💖简介:java、微信小程序、安卓;定制开发,远程调试 代码讲解,文档指导,ppt制作💖 精彩专栏推荐订阅:在下方专栏&#x1…

    17.4 合并购物车

    分析 用户登录后,将Cookie中的购物车商品合并到redis数据库中。如果此时redis中已经有相同id的商品,则使用Cookie中的数据覆盖redis中的数据。 合并功能需要在用户登录后实现,但登录视图中应避免过多与登录逻辑无关的逻辑,所以考虑…

    RK3588消费级8K VR一体机 是否有坑?

    ​​芯片平台​​​​定位场景​​​​核心优势​​​​消费级功能性短板​​全志H8/RK3288入门级VR低成本、基础性能稳定算力弱(4*A55)、无NPU、显示分辨率仅1080P高通XR1中端VR/AR均衡性能(Adreno 615 GPU)仅WiFi5、续航≤4小时…

    基于Spring Boot校园二手交易平台系统设计与实现 二手交易系统 交易平台小程序

    🔥作者:it毕设实战小研🔥 💖简介:java、微信小程序、安卓;定制开发,远程调试 代码讲解,文档指导,ppt制作💖 精彩专栏推荐订阅:在下方专栏&#x1…

    Nginx 服务器常用操作

    一. Nginx 常用配置 1. Nginx 总配置文件 nginx 安装目录下的 nginx.conf 文件: # 指定 Nginx worker 进程运行的系统用户 user nginx; # 自动根据 CPU 核心数启动相应数量的 worker 进程,充分利用多核。 worker_processes auto; # 自动将 worker 进程绑定到特定 …

    PHP官方及第三方下载地址全指南(2025最新版)

    PHP官方及第三方下载地址全指南(2025最新版) 本文整理了PHP官方及主流第三方下载渠道,包含PHP 5.5至8.4各版本的直接下载链接,助您快速获取安全可靠的PHP环境。 一、PHP官方下载渠道 1.1 全球主站下载 网址:https://…

    深度剖析Redisson分布式锁项目实战

    今天在练手项目中也是遇到了许多新的技术,其中我认为最深刻的还是Redisson分布式锁,这里我就结合一下我项目中用到Redisson分布式锁的代码来讲述一下Redisson分布式锁,希望可以帮助大家更深刻地理解这项技术。在之前的文章中我已经讲过Rediss…

    第四天-创建一个Classic CAN(经典CAN2.0)/CANFD的系统描述ARXML文件

    【ARXML专题】-构建CAN/CANFD通信系统:ARXML实战指南 汽车神经系统的"高速公路" 想象一辆现代汽车如同人体,电子控制单元(ECU)是器官,而CAN总线就是连接它们的神经系统。在自动驾驶时代,传统CAN2.0的"乡间小路"已无法满足数据传输需求,CANFD的"…

    用架构建模工具Sparx EA绘制企业转型路线图

    企业数字化转型面临诸多挑战:信息壁垒导致各部门协同困难,资源投入缺乏科学评估,潜在风险难以提前预判。这些问题不仅拖慢转型进程,还可能引发高昂的试错成本。 本文将阐述如何运用架构建模工具Sparx EA的核心功能——可视化路线…

    STM32——GPIO

    总 :STM32——学习总纲 参考资料: STM32F1系列参考手册-V10(中) 一、GPIO简介 1.1 GPIO 特点 1.2 GPIO 电气特性* stm32芯片资料STM32F103ZET6(English) 1.3 GPIO 引脚分布 电源引脚:V开头 晶振引脚: …

    NUX MG-400 吉他效果器功能原理介绍

    NUX MG-400 是一款多功能数字吉他效果器,它的核心原理就是把吉他的模拟信号,通过 A/D 转换变成数字信号 → 在 DSP 芯片上做建模运算 → 再通过 D/A 转换还原成模拟信号输出。 它的硬件 软件协作设计,基本可以拆成几个模块来看: …

    Linux——进程管理和计划任务管理

    文章目录前言一、程序与进程的关系1.1 程序与进程的定义1.2 父进程与子进程二、查看进程信息2.1 ps 命令(重点)2.2 动态查看进程信息top命令(重点)2.3 pgrep命令查询进程信息2.4 pstree命令以树形结构列出进程信息三、进程的启动方…

    阿里云TranslateGeneral - 机器翻译SDK-自己封账单文件版本—仙盟创梦IDE

    仙盟创梦IDE代码<?php /*** 阿里云机器翻译通用版API调用工具* 文档参考&#xff1a;https://help.aliyun.com/zh/machine-translation/developer-reference/api-alimt-2018-10-12-translategeneral*/ class AliyunTranslate {// 阿里云访问密钥private $accessKeyId;priva…

    新字符设备驱动实验

    经过前两章实验的实战操作&#xff0c;我们已经掌握了 Linux 字符设备驱动开发的基本步骤&#xff0c;字符 设备驱动开发重点是使用 register_chrdev 函数注册字符设备&#xff0c;当不再使用设备的时候就使用 unregister_chrdev 函数注销字符设备&#xff0c;驱动模块加载成功…

    【更新公告】C++算法·线段树

    之前的线段树知识都忘了qwq 现在在重新学线段树 下一篇就是写线段树了&#xff0c;例题已经找好了 A了1遍&#xff0c;但是用的玄学代码ee 下面是更新公告 更新公告 更新模式改为2~3天1篇 但是绝对高质量&#xff01;&#xff01; (平均质量分93够吗qwq) 如果例题好找尽量给出2…

    pyqtgraph 库 右键菜单栏插件汉化

    第一步&#xff0c;打开pyqtgraph文件夹。 第二步&#xff1a;打开graphicsItems&#xff0c;将PlotItem和ViewBox中的.py文件中的英文替换为中文&#xff0c;运行软件即可看到插件右键的菜单栏成为中文。 第三步&#xff1a;GraphicsScene中的&#xff0c;等找到相应的右键菜单…