Java
2024-07-01 21:16:42 0 举报
AI智能生成
登录查看完整内容
并发的普通知识点
作者其他创作
大纲/内容
避免了单继承的局限性,方便一个对象同时被多个线程使用
实现 Runnable
继承Thread类,其本质上是实现Runnable接口
使用线程池的概念,实现这个接口,重现的是的call方法,new Executors.newFixed...... 然后submit提交
实现Callable接口
使用线程池
线程的实现
star方式启动是启动了线程并且将线程调整到了就绪态(这时只要获得时间片就可以启动了,然后再调用run的方法)
run的方法调用相当于main的线程调用了方法
线程启动方式
外框
线程的实现和启动
两者的主要区别:sleep方法没有释放锁,wait方法会先释放锁
wait必须在同步代码块中使用,但是sleep可以在任何地方使用
不同点
两者都会暂时停止线程的运行
wait常用于线程之间的交互和通信,sleep常用于线程的暂停
wait不能够自己唤醒,必须要进行notify或者notifyall来唤醒,sleep到时间了可以自己唤醒自己
共同点
sleep() 方法和 wait() 方法区
是否响应中断,lock中可以使用interrupt中断等待,但是synchronize只能等待获取锁
lock是一个接口synchronize是一个关键字
lock可以通过trylock来判断是否获取了锁,但是synchronize不能
synchronize在发生异常的时候会自己释放锁,但是lock不会自己释放锁
synchronized是可重入锁,不能中断是非公平锁;Lock是可重入锁,可以判断锁,公平性可以自由选择
synchronize适合少量的代码同步问题,lock适用于大量的代码同步问题
区别
十分公平,严格遵守先来后到的顺序
公平锁
可以进行cpu的插队操作
非公平锁(默认)
Lock
synchronized和lock
互斥条件:该资源在同一时刻只能有一个线程占用
请求与保持条件:请求资源时被阻塞同时保持自己的资源不放
不剥夺条件:自己获得的资源没用完之前不能被强行的剥夺掉
循环等待:多个资源之间形成一个环形的资源等待关系
死锁具备的条件
破坏互斥条件:这东西不能破坏
破坏请求与保持:直接一下子申请所有资源,不请求了
破坏不剥夺条件:自己要的资源申请不到了就直接摆烂,自己的也释放了
破坏循环等待条件:资源进行排序,按照次序进行访问
如何避免死锁的发生(破坏上述至之一就行)
死锁
cpu调度的最小单位
线程之间共享进程的资源
线程切换的消耗比较低
线程
操作系统分配资源的最小单位
一个进程可以含有多个线程
进程
线程和进程
在一个时间段内,交替执行
并发
同一时刻一起发生
并行
并发和并行
并发和并行、线程和进程
可以使线程交替执行
使用这个的优势在哪
condition.await使线程进入等待的状态
condition.signalAll唤醒所有的线程
new 多个Condition然后直接用new 出的Condition.signal()
指定唤醒某一个线程的方法
Lock.new Condition可以产生
Condition同步监视器
生产者和消费者使用if判断可能会产生虚假唤醒的可能,使用while可以避免这种情况
普通方法不受锁的限制
synchronized锁的是对象的的调用者(new 的就算是一个)
锁的对象为static方法时,锁的时CLass
锁谁的几种情况
逻辑为使用lock锁进行数组复制再插入
copyOnWriteArrayList
copyOnWriteArraySet
CooncurrentHashMap
Collections类中有一系列sync开头的方法转化为线程安全的
线程安全的集合类
作用:用来替换Runnable的功能,重写的方法叫做call可以解决runnable没有返回类型的问题
FutureTask为Runnable的一个实现类,Calable可以当做入参给FutureTask
解决办法
使用futureTask.get()可以的得到返回值
get的方法可能会产生阻塞,因为他要等待返回结果
获取返回值的办法
Calable不能和Thread直接交互
Calable
允许一个或多个线程等待直到其他下线程中的一组操作完成的同步辅助
CountDownLatch.coutDown()实现数量减一
CountDownLatch减法计数器
new 是传入参数(多少次加法运算),一个线程(运算结束后执行该线程)
CycllicBarrier.await
CycllicBarrier加法计数器
设置可以获得信号的线程数量
如果当前的信号量已经都被使用,线程进入等待
Semaphore.acquire()获得信号量
信号量+1,唤醒等待的线程
Semaphore.release()释放信号量,放到finally函数中
Semaphore信号量
用来计数的
常用的辅助类
ReentrantReadWriteLock是读写锁一个实现类,其中有一对关联锁,一个只用于读,一个只用于写读可以被多线程同时读,写的时候只能够有一个线程去写
加锁:ReentrantReadWriteLock().readLock().lock()
解锁:ReentrantReadWriteLock().readLock().unlock()
读锁
加锁:ReentrantReadWriteLock().writeLock().Lock()
解锁:ReentrantReadWriteLock().writeLock().unLock()
写锁
读写锁
Collection的子类,与List和set类似
子主题
含义’
ArrayBlockingQueue
写了只能等待拿出来后才能继续写
put向里面放元素 take从里面取元素
同步队列SynchronizeQueue
LinkedBlockingQueue
阻塞队列BlockingQueue
双端队列Deque
非阻塞的队列AbstractQueue
实现类
Queue
Stream流式运算
创建一个单线程的线程池,池中只有一个线程在直接,保证线程执行的顺序
newSigleThreadExector
创建一个固定大小的线程池,大小一旦到最大时就会保持不变
newFixedThreadPool
遇强则强,不对大小进行限制,是服务器最大的线程数
newCachedThreadPool
定时周期的执行任务
newScheduledThreadPool
四种创建的方式
Executors
FixedThreadPool和SigleThreadExector请求队列的最大长度设置的长度过大,可能会造成OOM溢出的问题
CachedThreadPool和ScheduledThreadPool最大线程数设置的过大,可能回导致OOM异常
为什么建议使用原生的创建线程池的方法
AbortPolicy
CallerRunsPolicy
DisCardolddesPolicy
不进行处理,并抛出异常
DisCardPolicy(默认的)
线程池的四种拒绝策略
线程池
将主内存中的数据取出来
read
将read取出来的操作加载到工作内存中
load
从工作内存中的数据放到执行内存中使用
use
将执行引擎运行后的结果放到工作内存中
assign
将工作内存中的数据放写入回去
write
将写入的结果存储起来
store
JMM时一种想想出来的线程内存关系模型 ,其中包含了大概四对操作
JMM
Java虚拟机提供的轻量级的同步机制
一旦被标记的变量发生改变后,立刻回显到主内存和其他线程的工作内存中去
可见性
Atomic integer.compareand set
CAs
使用automic(原子类)、底层的操作都是调用的native方法,直接在内存中进行操作
延申问题:如果不用synchronization
不保证原子性
程序最终的执行顺序可能由于处理器在考虑了参数的依赖顺序之后进行重新排序的操作,虽然不会改变结果,但是有可能会调整代码的执行顺序
代码的最终执行是需要经过几个步骤的:元代码->编译器优化的重排->指令并行也可能进行重排->内存系统也会进行重排->执行
指令重排是什么
cpu在执行数据时有一层内存屏障
为何能禁止指令重排
禁止指令重排
volate
多线程
参数的类型可以省略
如果方法只有一个参数()可以省略
如果是无返回值的且只有一行代码{}也可以省略
如果有返回值且只有return语句的省略{}的同时,return也必须省掉
语法注意的点
F1 f1=其他类::其他方法;
语法
相当于其他类的其他方法替换了F1中的方法
含义
方法引用
Lambda
JAVA8的一些东西
(Boot ClassLoader)根加载器
(PlatForm Class Loader)平台加载器
(App ClassLoader)应用加载器
自定义加载器
四种加载器
加载器
存放Java方法调用过程中的栈帧。用于管理Java方法的调用
栈
存放对象实例、实例变量、数组,包括新生代(伊甸园区、幸存区S0和S1)和老年代。
堆
本地方法栈
方法区
程序计数器
jvm运行时区的组成
JVM
插入数据是会进行长度判断,如果长度达到了初始长度则会调用nsureCapacity()进行自动扩容,一般情况下扩容时按照原来的1.5倍进行扩容,但是由于扩容的操作是将原有的数据复制到信的数组中,这样付出的代价会比较高,如果数量较多的话最好先设置一个初始量
自动扩容
ArrayList
简单概括其特点:有序可重复、底层为双向的链表、增删快但是查找比较慢、不是线程安全的,如果需要使用的话可以将其使用Collections.synchronizedList()进行修饰
双向链表的每个节点用内部类Node表示。LinkedList通过first和last引用分别指向链表的第一个和最后一个元素。注意这里没有所谓的哑元,当链表为空的时候first和last都指向null。
LinkedList
Java里有一个叫做Stack的类,却没有叫做Queue的类(它是个接口名字)。当需要使用栈时,Java已不推荐使用Stack,而是推荐使用更高效的ArrayDeque
Stack
Queue接口继承自Collection接口
Queue(这个不是类只是一个接口)
Collection
简单的概括其特点:key-value的形式,key可以为null但是不可以重复,如果放置重复的值时会将原来的值进行覆盖,存放的数据也没有顺序可言
开放地址
冲突链表(Java7使用)
处理冲突点的方式
7采用的是头插法,8采用的是尾插法
7和8的差异
HashMap
Map
集合
notify和notifyall的区别:notify在等待池中随机去唤醒一个,notifyAll就是唤醒线程池中所有的线程
自旋锁
种类
不需要操作系统进行调度的锁
轻量级锁
在锁队列中等待的锁,如果需要执行则需要操作系统进行调度的锁
重量级锁
不一定,轻量级进行自选需要占用CPU的资源,如果程序执行的时间较长或现线程较多的时候不如重量级的锁
轻量级的锁一定比重量级的锁效率高吗?
锁
JAVA
0 条评论
回复 删除
下一页