Java 多线程 学习笔记
2024-07-15 11:31:26 3 举报
AI智能生成
Java 多线程 学习笔记
作者其他创作
大纲/内容
volatile
作用
保证内存可见性
防止指令重排
保证对long和double类型赋值的原子操作
注意:不保证操作的原子性
指令重排
概念
带来的问题
问题1:A线程指令重排导致B线程出错
问题2:指令重排导致单例模式失效
解决方案
使用条件
1.对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
2.该变量没有包含在具有其他变量的不变式中
使用建议
在两个或者更多的线程需要访问的成员变量上使用volatile
当要访问的变量已在synchronized代码块中,或者为常量时,没必要使用volatile
由于使用volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字
总结
synchronized
作用:确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性
对于普通方法,锁是当前实例对象
对于静态方法,锁是当前类的Class对象
对于同步方法块,锁是synchonized括号里配置的对象
实现线程的方式
继承 Thread 类
实现 Runnable 接口
实现 Callable 接口
线程的状态
初始状态(New)
运行状态(Runnable)
就绪
运行
阻塞状态(Blocked)
等待状态(Waiting)
超时等待状态(Time_Waiting)
终止状态(Terminated)
线程的中断
Object.wait(),Thread.sleep(),Thread.join() 方法使用线程进行等待状态
再调用 Thread.interrupt() 中断线程
在线程内会产生 java.lang.InterruptedException 异常
Thread.isInterrupted() 检查是否收到了中断请求,不清除中断标记
Thread.interrupted() 检查是否收到了中断请求,并清除中断标记
对象等待/通知相关方法
notify()
nofityAll()
wait()
wait(long)
wait(long, int)
Java中的13个原子操作类
第一类
AtomicBoolean
AtomicInteger
int getAndIncrement()
AtomicLong
AtomicReference
AtomicStampedReference
AtomicMarkableReference
第二类
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
第三类
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
公共方法
boolean compareAndSet(...);
Lock接口
注意:不要将获取锁的过程写在try块中
提供synchronized不具备的特性
尝试非阻塞地获取锁
能被中断地获取锁
超时获取锁
API方法
lock()
unlock()
tryLock()
tryLock(long, TimeUnit)
lockInterruptibly()
newCondition()
实现类
ReentrantLock(重入锁):能够支持一个线程对资源重复加锁
ReentrantReadWriteLock(读写锁)
readLock()
writeLock()
Condition接口
await():使线程进入等待状态,直到被通知(signal)
signal():唤醒一个等待在Condition上的线程
signalAll():唤醒所有等待在Condition上的线程
awaitNanos(long timeout)
awaitUnit(Date deadlne)
LockSupport工具
park():阻塞当前线程
parkNanos(long):阻塞当前线程,最长不超过多少纳秒
parkUntil(long):阻塞当前线程,直到deadline时间
unpark(Thread thread):唤醒处于阻塞状态的线程thread
并发工具类
Semaphore
作用:限制线程并发的数量
主要方法
acquire()
release()
tryAcquire()
构造函数:new Semaphore(int permits)
permits代表同一时刻,最多允许多少个线程同时执行acquire()和release()之间的代码
Exchanger
作用:可以使2个线程之间传输数据
主要方法
exchange(T data):阻塞等待其他线程来取得数据
exchange(T data, long timeout, TimeUnit unit)
CoutDownLatch
作用:给定一个计数,当使用这个类的线程判断计数不为0时,则呈wait状态,如果为0则继续运行
主要方法
await():调用此方法时判断计数是否为0,如果不为0则呈等待状态
await(long timeout, TimeUnit unit)
countDown():调用此方法将计数减1
getCount()
注意:计数无法被重置,如果需要重置计数,请考虑使用CyclicBarrier
CyclicBarrier
作用
具有CountDownLatch所有功能
可以实现屏障等待的功能
多个线程之间相互等待,任何一个线程完成之前,所有的线程都必须等待
主要方法
await():让线程呈等待状态
getNumberWaiting:得到到达屏障点的线程数
getParties():取得parties个数
reset():重置屏障
注意:不能动态添加parties计数,可以通过Phaser类解决
Phaser
作用:对计数的操作是加法操作,可以设置多屏障
主要方法
arriveAndAwaitAdvance():当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障继续执行
arriveAndDeregister():使用当前线程退出,并且使parties值减1
getPhase():获取已经到达第几个屏障
getRegisteredParties():获得注册的parties数量
register():动态添加1个parties值
bulkRegister():批量增加parties数量
getArrivedParties():获得已经被使用的parties个数
getUnarrivedParties():获得未被使用的parties个数
arrive():使parties值加1,并且不在屏障处等待,直接向下面的代码继续运行
awaitAdvance(int phase):如果传入参数phase值和当前getPhase()方法返回值一样,则在屏障处等待,否则继续向下运行
forceTermination():使屏障功能失效
isTerminated():判断屏障是否已经销毁
fork/join框架
作用
更好地利用底层平台上的多核CPU和多处理器来进行并行处理
解决问题时通常使用分治(divide and conquer)算法或map/reduce算法来进行
关键类
RecursiveAction:没有返回值
fork:执行任务
join:等等任务执行结果
RecursiveTask:有返回值
ForkJoinPool:执行任务
原理
递归调用分解任务
任务窃取算法
示例
Executor框架
任务
Runnable
Callable
任务执行
接口:Executor
void execute(...)
Future submit(...)
接口:ExecutorService
ThreadPoolExecutor
ScheduledThreadPoolExecutor
异步计算
接口:Future
缺点:阻塞同步性
类:FutureTask
Executors工具类
ExecutorService newFixedThreadPool(...)
ExecutorService newSingleThreadPool(...)
ExecutorService newCachedThreadPool(...)
ScheduledExecutorService newScheduledThreadPool(...)
ScheduledExecutorService newSingleThreadScheduledExecutor(...)
Callable
Callable callable(Runnable task, T result)
线程池(ThreadPoolExecutor)
好处
降低资源消耗
提高响应速度
提高线程的可管理性
接口:CompletionServivce
实现类:ExcutorCompletionServivce
特性:解决Future的阻塞同步性问题
方法
Future submit(Runable task, T result)
take():取得最先完成任务的Future对象,谁执行时间最短谁最先返回,方法阻塞
poll():获取并移除表示下一个已完成任务的Future,如果不存在这样的任务返回null,方法无阻塞
并发集合框架
非阻塞队列
含义
队列里没有数据时,操作队列出现异常或返回null
不具有等待/阻塞的特色
常用类
ConcurrentHashMap:线程安全的Map
V putIfAbsent
boolean remove(K key, V value)
replace(K key, V oldValue, V newValue)
ConcurrentSkipListMap:线程安全的可排序Map
ConcurrentSkipListSet:线程安全的可排序Set
ConcurrentLinkedQueue:线程安全的队列Queue(只能操作列头)
方法 poll() : 当没有获得数据时返回null,如果有数据时则移除表头,并返回表头项
方法 element() : 当没有获得数据时出现异常,如果有数据时则移除表头,并返回表头项
方法 peek() : 当没有获得数据时返回null,如果有数据时则不移除表头,并返回表头项
ConcurrentLinkedDeque:线程安全的Deque(支持操作列头列尾)
CopyOnWriteArrayList:线程安全的ArrayList
CopyOnWriteArraySet:线程安全的Set
阻塞队列
含义
队列里没有数据时,从队列里取东西的操作将会被阻塞进入等待状态,直到队列里添加了元素才会被唤醒
当队列是满的,试图往队列中存放元素的操作也会被阻塞进入等待状态,直到队列里有剩余的空间才会被唤醒
常用类
ArrayBlockingQueue:一种有界阻塞队列
PriorityBlockingQueue:一种优先级队列
LinkedBlockingQueue:一种只支持列头操作的无界阻塞队列
LinkedBlockingDeque:一种支持列头列尾操作的无界阻塞队列
SynchronousQueue:一种插入操作必须等待另一个线程的对应移除操作,反之亦然的阻塞队列
DelayQueue:一种延时执行任务的队列
线程间变量的传递
ThreadLocal
作用:同一线程上设置或获取变量,为每一个线程创建一个单独的变量副本,故而每个线程都可以独立地改变自己所拥有的变量副本,而不会影响其他线程所对应的副本。
缺点:不能实现父线程到子线程的值传递
用法:
ThreadLocalMap:ThreadLocal内部还有一个静态内部类,是实现线程隔离机制的关键
注意:存在内存泄漏的风险
InheritableThreadLocal
作用:可以完成父线程到子线程的值传递
缺点:对于使用线程池等会缓存线程的组件的情况无法重复使用
用法:
TransmittableThreadLocal
作用:线程池中的线程间传递变量
用法:
0 条评论
下一页
图形选择
思维导图
主题
补充说明
AI生成
提示
关闭后当前内容将不会保存,是否继续?
取消
确定