java多线程
2024-02-21 11:33:17 0 举报
AI智能生成
多线程
作者其他创作
大纲/内容
认识线程
<span>线程定义</span><br>
<span>线程分类</span><br>
<span><span style="font-weight: bold; line-height: 1.45;">守护线程</span></span><br>
<span><span style="font-weight: bold; line-height: 1.45;">用户线程</span></span><br>
<b>线程优先级</b>
<span>线程内存模型</span><br>
<span>线程状态</span><br>
<span>NEW:初始状态</span><br>
<span>RUNABLE:运行状态</span><br>
<span>BLOCKED:阻塞i状态</span><br>
<span>WAITING:等待状态</span><br>
<span>TIME_WAITING:超时状态</span><br>
<span>TERMINATED:终止状态</span><br>
线程与进程通信
线程通信方式
进程通信
通信含义
通信方式
管道:半双工
信号量:计数器
消息队列
信号
共享内存
套接字
线程创建
继承Thread类重写run方法
实现Runable接口
实现Callable接口,重写call方法<br>
异步计算结果:Future/FutureTask
V get()<br>
V get(long timeout,TimeUtil unit)<br>
Thread类
对象方法
<span><span style="text-decoration: underline;">启动start()方法</span></span><br>
<u style="">中断interrupt() /判断是否被中断isInterrupted</u>
<u style="">等待线程t 结束 t.join()方法</u>
<span><span style="text-decoration: underline;">设置守护线程setDaemon(boolean on)</span></span><br>
<u style="">设置优先级setProority(int newProority)</u>
Object方法:线程等待wait(long)/wait(long timeout, int nanos)<br>
<span><span style="font-family: 黑体; text-decoration: underline;">释放持有的锁</span></span><br>
<u style="">Object方法:唤醒线程notify()/notifyAll()</u>
静态方法<br>
<span><span style="font-family: 黑体; text-decoration: underline;">获取当前线程currentThread()</span></span><br>
<span><span style="font-family: 黑体; text-decoration: underline;">睡眠sleep(long)</span></span><br>
<span><span style="font-family: 黑体; text-decoration: underline;">不会释放锁</span></span><br>
<font face="黑体"><u style="">让出CPU资源yield()</u></font>
<span><span style="font-family: 黑体; text-decoration: underline;">设置中断标志位为true的interrupted()</span></span><br>
线程同步
锁的种类
偏向锁
优点
轻量级锁
子主题
重量级锁
子主题
独占锁:同一时刻只有一个线程获取到锁,而其它获取锁的线程只能处于同步队列中等待,只有获取锁的线程释放了锁,后继的线程才能够获得锁
共享锁
公平锁
非公平锁
隐式锁synchronized
如何实现同步
synchronized同步代码块:使用monitorenter和moniterexit
synchronized方法:使用方法表的ACC_SYNCHRONIED实现同步
内存可见性
可重入性
原子性
非公平锁
无法保证对锁先进行请求一定先被满足
volatile<br>
如何实现<br>
volatile读写利用内存屏障实现其语义<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">不能保证原子性</span></span><br>
对于任意单个volatile变量的读写操作具有原子性,但是对于volatile++这种无法保证原子性
内存可见性<br>
volatile读:都一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程从主内存中获取该变量
volatile写:写一个volatile变量,JMM会把该线程对应本地内存中的共享变量刷新到主内存
final<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">禁止重排序</span></span><br>
static<br>
static方法操作static变量时会引发线程安全问题
Lock接口<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">与synchronized区别的特点</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">尝试非阻塞的获取锁</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">能被中断地获取锁</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">超时获取锁</span></span><br>
基于AQS实现的同步工具
信号量Semaphore<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">定义:用来控制同时访问特定资源的线程数量,他们都过协调个线程,以保证合理的使用公共资源</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">应用场景:做流量控制,公共资源有限的场景例如数据库链接</span></span><br>
栅栏CyclicBarrier<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">适用于多线程计算数据,最后合并:比如归并排序此类任务</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">定义:让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被拦截的线程才会继续运行</span></span><br>
每个线程调用await()方法告诉栅栏CyclicBarrier已经到达屏障
<span><span style="line-height: 1.45;-en-clipboard:true;">构造函数:</span></span>CyclicBarrier(int parties, Runnable barrierAction)<br>
barrierAction:表示到达屏障后优先执行的线程 /parties:表示屏障需要拦截的数量<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">计数器可以重置reset()方法</span></span><br>
闭锁CountDownLatch<br>
构造函数:必须要传递一个整型参数作为计数器的值CountDownLatch(int count)<br>
阻塞等待计数器为0 :await()
boolean await(long timeout, TimeUnit unit)<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">计数器减1 countDown()</span></span><br>
计数器只能使用一次
显示锁<br>
ReentrantLock<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">公平锁与非公平锁</span></span><br>
<span><span style="line-height: 1.45;-en-clipboard:true;">加锁lock()</span></span><br>
解锁unlock
尝试获取锁tryLock:在timeout时间内阻塞式地获取锁,成功返回true,超时返回false,同时响应中断信息,抛出异常
ReentrantReadWriteLock<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">适用于读多写少的场景</span></span><br>
公平锁与非公平锁<br>
readLock():共享锁/writeLock():独占锁<br>
读读共享,读写互斥,写读互斥,写写互斥
读写状态设计:高16位表示读,底16位表示写<br>
锁降级<br>
写锁降级为读锁:把持住写锁,再获取到读锁,所后释放之前拥有的写锁的过程<br>
<span><span style="line-height: 1.45;-en-clipboard:true;">禁止重排序</span></span><br>
FutureTask
线程间通信
基于共享内存的通信
共享上下文
内部类
通道
ThreadLocal
隔离性
重写initalValue解决get()返回null问题、
InheritableThreadLocal:实现父线程与子线程的通信
避免内存泄漏:需要调用ThreadLocal.remove()方法
基于线程调度的通信
wait/notify/notifyAll
synchronized同步方法或者同步块中使用
阻塞等待被唤醒,除非被中断wait()
wait(long timeout):释放持有锁,但是不响应中断
唤醒一个或者所有等待的线程notify/notifyAll
wait被执行后,会自动释放锁,而notify被执行后,锁没有立即释放,由synchronized同步块结束时释放
join
join(long )释放锁
显式锁Lock的Condition<br>
创建:Condition condition = new ReentrantLock().newCondition();
获取显式锁Lock中使用
await:释放持有的锁,并且响应中断
singal()/singalAll():响应中断
线程异常捕获
UncaughtExceptionHandler
对象示例设置
Thread实现类级别设置
线程组重载UncaughtException
线程池
<span><span style="line-height: 1.45;">线程池的优点</span><span style="line-height: 1.45;"></span></span>
<span><span style="line-height: 1.45;">降低资源消耗:通过重复利用已经创建的线程降低线程创建和销毁造成的损耗</span><span style="line-height: 1.45;"></span></span>
<span><span style="line-height: 1.45;">提高效应速度:任务不需要等到线程创建就能立即执行</span><span style="line-height: 1.45;"></span></span>
<span><span style="line-height: 1.45;">提高线程的可管理性:线程池统一分配,调优和监控</span><span style="line-height: 1.45;"></span></span>
<span><span style="line-height: 1.45;">线程池接受新任务的流程</span></span><br>
<span><span style="line-height: 1.45;"><font color="#ffffff">(1)线程池判断核心线程池里面的线程是否都在执行任务</font></span></span><br>
NO:创建一个新的工作线程执行任务
<span><span style="line-height: 1.45;">YES:执行流程(2)</span></span><br>
<span><span style="line-height: 1.45;">(2)线程池判断工作队列是否满了</span></span><br>
NO:没有满,则将新提交的任务存储到工作队列中
YES;满了,进入(3)
<span><span style="line-height: 1.45;">(3)线程池判断线程池的线程是否都处于工作状态。</span></span><br>
<span><span style="line-height: 1.45;">NO:没有都处于工作状态,则创建一个新的工作线程来执行任务</span></span><br>
<span><span style="line-height: 1.45;">如果已经饱和了,则交给饱和策略来处理任务</span></span><br>
线程池的组成部分
<span><span style="line-height: 1.45;">管理器</span></span><br>
<span><span style="line-height: 1.45;">工作线程</span></span><br>
<span><span style="line-height: 1.45;">任务接口</span></span><br>
<span><span style="line-height: 1.45;">等待队列</span></span><br>
线程池的创建ThreadPoolExecutor的重要参数
1.corePoolSize:核心线程数(线程池的基本大小)
当提交一个新任务时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池的基本大小时就不在创建了。<br>
调用prestartCoreThread()方法会让线程池提前创建并启动所有线程
2.maximumPoolSize:线程池最大数量
如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务
如果使用了无界队列,那么这个参数就会失效
3.long keepAliveTime:线程活动保持时间
线程池的工作线程控线后,保持存活的时间
4.TimeUnit unit:线程保持存活时间的单位
5.BlockingQueue<Runnable> workQueue:任务队列
作用:用于保存等待执行的任务的阻塞队列
ArraBlockingQueue:基于数组结构的有界阻塞队列;按照FIFO先进先出的原则对元素进行排序
LinkedBlockingQueue:基于链表结构的无界阻塞队列;按照FIFO先进先出的原则对元素进行排序
Executors.newFixedThreadPool()以及Executors.newSingleThreadExecutor使用该队列
SynchronousQueue:一个不存储元素的有界阻塞队列;每个插入操作必须等待另一个线程的一处操作,否则插入操作会一直阻塞
Executors.newCachedThreadPool()
PriorityBlockingQueue:一个具有优先级的无限阻塞队列
DelayQueue封装了一个ProorityBlockingQueue
6.ThreadFactory threadFactory:用于设置线程工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字
7.RejectedExecutionHandler handler:饱和策略
当队列和线程池都已经满了,说明线程池饱和状态,必须采取一种策略处理提交的新任务。
AbortPolicy:直接抛出异常
CallerRunsPolicy:只用调用者所在线程来运行任务
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
DiscardPolicy:不处理,直接丢弃
<span><span style="line-height: 1.45;">线程池的其他操作</span></span><br>
线程池提交任务
execute:提交不需要返回值的任务
submit:提交需要返回值的任务
返回Future对象,Future.get()得到返回值
线程池的关闭
void shutdown():将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程
List<Runnable> shutdownNow():将线程池的状态设置为STOP,然后尝试停止所有正在执行或者暂停任务的线程,并返回等待执行任务的列表
线程池的监控
taskCount:线程池所需要执行的任务数量
completedTaskCount:线程池再运行过程中已完成的任务数量
largestPoolSize:线程池里曾经创建过的最大线程数量,查看是否满过
getPoolSize:线程池的线程数量,线程池不晓辉的话,线程池的线程不会自动销毁,所以这个数字只增不减
getActiveCount:获取活动线程数量
beforeExecute:线程任务执行前
afterExecute:x线程任务执行后
terminated:线程池关闭前执行
<span><span style="line-height: 1.45;">Executors框架</span></span><br>
ThreadPoolExecutor
ExecutorService newFixedThreadPool(int nThreads):创建一个固定线程数量的线程池
为了满足资源管理的需求,需要限制当前线程数量的应用场景。适用于负载比较重的服务器
ExecutorService newSingleThreadExecutor():创建使用单个线程的线程池
需要保证顺序执行各个人物,并且在任意时间点上,不会有多个线程是活动的应用场景
ExecutorService newCachedThreadPool():创建一个会根据需要创建新线程的CacheThreadPool
CacheThreadPool是大小无界的线程池,适合于执行很多短期异步任务的小程序,或者负载较轻的服务器
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor:包含若干线程 / SingleThreadScheduledExecutor:只包含一个线程
作用:用来在给定的延迟之后运行任务,或者顶起执行任务。
采用的队列为无界队列DelayQueue
ExecutorService
提交任务:submit()
拒绝新任务,等待任务全部结束关闭线程池shutdown()
尝试立刻关闭线程池并返回等待执行的任务列表List<Runnable> shutdownNow()
FutureTask
<span><span style="line-height: 1.45;">ExecutorService</span></span><br>
原子类
基本类
AtomicInteger
AtomicBoolean
AtomicLong
<span><span style="line-height: 1.45;">引用类型</span></span><br>
AtomicReference
AtomicStampedReference
解决ABA问题
AtomicMarkableReference
<span><span style="line-height: 1.45;">数组类型</span></span><br>
AtomicReferenceArray
AtomicIntegerArray
AtomicLongArray
属性原子修改器
1.必须使用静态方法newUpdater创建一个更新器;3.更新字段的属性必须使用public volatile
AtomicIntegerFieldUpdater<br>
AtomicLongFieldUpdater<br>
AtomicReferenceFieldUpdater
0 条评论
下一页
为你推荐
查看更多