一、Lock接口
1)、多线程涉及到的基本概念
资源类、操作、线程、高内聚、低耦合
2)、使用
①实现类
ReentrantLock(可重入锁)
②基本方法
lock() 上锁、unlock() 解锁
二、线程间通信
1)、经典问题
生产者&&消费者
Ps:注意多线程之间的虚假唤醒
解决:对于wait()方法使用循环判断
2)、使用synchronized
对应方法:wait()、notify()
3)、使用lock
await()、signal()
Ps:让当前线程睡眠:TimeUnit.
三、线程安全集合
可变操作通过生成底层数组的新副本来实现:写时复制技术
CopyOnWriteArrayList
四、实现多线程的方法
1)、继承thread类
2)、实现runnable接口
3)、实现callable接口
①通过FuntureTask来开启线程
②在主线程需要执行较为耗时的操作时,把这些作业交由Future对象在后台完成
主线程可通过Future对象来获得后台作业的计算结果或执行状态
仅在计算完成时才能检索结果,否则主线程会一直阻塞到任务完成
该线程只能计算一次(启动一次)
4)、java的线程池
五、Util工具类
1)、CountDownLatch(减少计数)
await():被调用时,该线程会阻塞
coutnDown():计数器减一,当计数器为0时,因await阻塞的方法会被唤醒
2)、CyclicBarrier(循环栅栏)
让一组线程到达一个屏障(同步点)时被阻塞
直到最后一个线程到达同步点才会开门,所有阻塞的线程继续干活
await():阻塞
3)、Semaphore(信号灯)
acquire():抢占资源,信号量减一
要么成功获取信号量,要么一直等待下去,直到有线程释放信号量,或超时
release():释放资源,信号量加一
六、读写锁
ReadWriteLock——>ReentrantReadWriteLock
.writeLock.lock():给写操作上锁
.readLock.lock():给读操作上锁
七、阻塞队列(BlockingQueue)
1)、阻塞
必须要阻塞/不得不阻塞,挂起/唤醒线程
阻塞队列:自动的生产者/消费者模式,减少实现的复杂度
2)、常用实现类
①ArrayBlockingQueue
数组结构组成的有界阻塞队列
②LinkedBlckingQueue
链表结构组成的有界(默认大小未Integer.MAX)阻塞队列
③SynchronousQueue
不存储元素的阻塞队列,即单个元素的队列
3)、方法
操作\结果 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
检查 | element() | peek() |
①抛异常:队满IllegalStateException、队空NoSuchElementException
②特殊值:插入(true/false)、移除(value/null)
③一直阻塞:队满,put时阻塞、队空,take阻塞
④超时退出:阻塞队列满时,队列阻塞生产/消费者一段时间,超过时间后线程退出
八、线程池
1)、优势
线程复用、控制最大并发数、管理线程
2)、实现
Executor接口、ExecutorService接口、ThreadPoolExecutor(常用实现类)
①工具类新建线程
Executors.newFixedThreadPool(n):一池n线程
Executors.newSingleThreadExecutor():一池一线程
Executors.newCachedThreadPool():可扩容线程池
②ThreadPoolExecutor建立线程池(7个参数)
参数 | 含义 |
---|---|
corePoolSize | 线程池中的常驻核心线程数(惰性加载,第一次执行的时候才会创建) |
maximumPoolSize | 线程池中能够容纳同时执行的最大线程数(大于等于1) |
keepAliveTime | 线程池中数量超过corePoolSize,且空闲时间达到keepAliveTime时,销毁多余线程 |
unit | keepAliveTime的单位 |
workQueue | 任务队列,被提交但尚未被执行的业务 |
threadFactory | 生成线程的线程工厂(一般使用默认) |
handler | 拒绝策略,队列满了且工作线程大于等于线程最大线程数 |
③一般使用ThreadPoolExecutor来建立线程池
FixedThreadPool(n)和SingleThreadExecutor()允许的请求队列长度为Integer.MAX,可能造成OOM
CachedThreadPool()允许线程数量为Integer.MAX,可能造成OOM
3)、运行原理
建立核心线程 —(核心满)—>
业务进入阻塞队列 —(阻塞满)—>
扩建非核心线程(先执行新来业务,非队列)—(全满)—>
拒绝—(度过高峰期,超过空闲时间)—>
非核心线程销毁
4)、线程池拒绝策略
①AbortPolicy(默认):抛异常RejectedExecutionException
②CallerRunsPolicy:“调用者运行”,既不抛弃任务,也不抛异常,退回任务
③DiscardOldestPolicy:抛弃队列中等待最久的任务,把当前任务加入队列
④DiscardPolicy:丢弃无法处理的任务,不予任何处理也不抛出异常
Ps:通过 new ThreadPoolExecutor. 来选择具体的拒绝策略