当前位置: 首页 > article >正文

【并发】知识点总结

线程基本概念

一、线程与进程
进程:程序的一次执行过程,系统运行程序的基本单位,进程是动态的。程序运行就是进程从创建,运行到消亡的过程。进程之间相互独立资源不共享。
线程:线程是比程序更小的执行单位,进程执行的过程中会产生多个线程。线程之间会共享方法区的资源,线程有自己的程序计数器、虚拟机栈和本地方法栈
二、 线程的生命周期和状态
NEW: 初始状态,线程被创建出来但没有被调用 start() 。
RUNNABLE: 运行状态,线程被调用了 start()等待运行的状态。
BLOCKED:阻塞状态,需要等待锁释放。
WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)。
TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待。
TERMINATED:终止状态,表示该线程已经运行完毕
三、线程上下文切换
线程在执行过程中会有自己的运行条件和状态(也称上下文),比如上文所说到过的程序计数器,栈信息等。当出现如下情况的时候,线程会从占用 CPU 状态中退出。

多线程

一、常见名词
并行与并发
并发:两个及两个以上的作业在同一 时间段 内执行。
并行:两个及两个以上的作业在同一 时刻 执行。
线程安全
线程安全指的是在多线程环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。
死锁
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
可以通过jmap、jstack等命令查看线程堆和栈内存的情况。
预防死锁
1.破坏请求与保持条件:一次性申请所有的资源。
2.破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
3.破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
避免死锁
避免死锁就是在资源分配时,借助于算法(比如银行家算法)对资源分配进行计算评估,使其进入安全状态。
二、实现多线程的方法
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口。Callable接口里定义的方法返回值,可以声明抛出异常。
4.线程池方式创建
三、停止一个正在运行的线程
1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2.使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。
3.使用interrupt方法中断线程。
四、线程池以及核心参数
线程池是一种管理线程的机制,它通过预先创建一组固定数量的线程来处理执行任务,从而避免了每次执行任务时都需要创建和销毁线程的开销。
实现方法
1.使用 Executors 工具类
2.使用 ThreadPoolExecutor 直接构造
3. 使用 ScheduledThreadPoolExecutor
参数
1.最大线程数maximumPoolSize:任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
2. 核心线程数corePoolSize:任务队列未达到队列容量时,最大可以同时运行的线程数量。
3. 活跃时间keepAliveTime
4. 阻塞队列workQueue: 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
5. 拒绝策略RejectedExecutionHandler
拒绝策略
如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,ThreadPoolExecutor 定义一些策略:
ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。
ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果你的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。
ThreadPoolExecutor.DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。
阻塞队列
LinkedBlockingQueue(有界阻塞队列)
SynchronousQueue(同步队列)
DelayedWorkQueue(延迟队列)
ArrayBlockingQueue(有界阻塞队列)
线程池的大小
CPU 密集型任务(N+1)
I/O 密集型任务(2N)

一、乐观锁与悲观锁
悲观锁
悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。
二、乐观锁
乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。
CAS算法
CAS 涉及到三个操作数:V:要更新的变量值(Var)E:预期值(Expected)N:拟写入的新值(New)当且仅当 V 的值等于 E 时,CAS 通过原子方式用新值 N 来更新 V 的值。如果不等,说明已经有其它线程更新了 V,则当前线程放弃更新。
三、synchronized关键字
synchronized 是 Java 中的一个关键字,翻译成中文是同步的意思,主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
四.volatile关键字
volatile 关键字可以保证变量的可见性,如果我们将变量声明为 volatile。volatile 关键字除了可以保证变量的可见性,还有一个重要的作用就是防止 JVM 的指令重排序。在对这个变量进行读写操作的时候,会通过插入特定的 内存屏障 的方式来禁止指令重排序。
五.ReentrantLock
ReentrantLock 实现了 Lock 接口,是一个可重入且独占式的锁,和 synchronized 关键字类似。不过,ReentrantLock 更灵活、更强大,增加了轮询、超时、中断、公平锁和非公平锁等高级功能。
可重入锁 也叫递归锁,指的是线程可以再次获取自己的内部锁。
等待可中断 : ReentrantLock提供了一种能够中断等待锁的线程的机制,通过 lock.lockInterruptibly() 来实现这个机制。也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
可实现公平锁 : ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。ReentrantLock默认情况是非公平的,可以通过 ReentrantLock类的ReentrantLock(boolean fair)构造方法来指定是否是公平的。
可实现选择性通知(锁可以绑定多个条件): synchronized关键字与wait()和notify()/notifyAll()方法相结合可以实现等待/通知机制。ReentrantLock类当然也可以实现,但是需要借助于Condition接口与newCondition()方法。


http://www.kler.cn/news/336457.html

相关文章:

  • TryHackMe 第5天 | Pre Security (四)
  • 提升开机速度:有效管理Windows电脑自启动项,打开、关闭自启动项教程分享
  • Python - HTTP servers
  • 计算机毕业设计 基于SpringBoot和Vue的课程教学平台的设计与实现 Java实战项目 附源码+文档+视频讲解
  • 短剧小程序短剧APP在线追剧APP网剧推广分销微短剧小剧场小程序集师知识付费集师短剧小程序集师小剧场小程序集师在线追剧小程序源码
  • 学习记录:js算法(五十六):从前序与中序遍历序列构造二叉树
  • 【AIGC】2022-NIPS-视频扩散模型
  • 房地产销售|基于springBoot的房地产销售管理系统设计与实现(附项目源码+论文+数据库)
  • 方舟开发框架(ArkUI)可运行 OpenHarmony、HarmonyOS、Android、iOS等操作系统
  • 大数据新视界 --大数据大厂之大数据驱动智能客服 -- 提升客户体验的核心动力
  • 【SQL】深入理解SQL:从基础概念到常用命令
  • Python(九)-导入模块
  • wpf加载带材料的3D模型(下载的3D预览一样有纹理)
  • Linux的环境变量
  • Java中的标识符和关键字
  • C语言文件操作(上)(27)
  • 基于STM32的超声波测距仪设计
  • 【rCore OS 开源操作系统】Rust 枚举与模式匹配
  • 单链表(纯代码)
  • SQL Server—约束和主键外键详解