JUC-多线程
2020-06-28 10:50:22 1 举报
AI智能生成
JUC
作者其他创作
大纲/内容
并发集合类<br>
Collection<br>
List<br>
vector 不推荐使用已废弃<br>
Conllections.synchronizedList 效率低
CopyOnwriterArrayList Lock锁实现
COW策略
Set
Collections.synchronizedSet 效率低
CopyOnwriteArraySet<br>
Queue
阻塞队列:BlockingQueue
ArrayBlockingQueue<br>
LinkedBlockingQueue<br>
SynchronousQueue
同步队列
队列中只允许存储一个元素<br>
AbstractQueue<br>
四组API
抛出异常
添加:add()<br>
删除:remove()<br>
判断队首:element()<br>
不抛出异常有返回值
添加:offer()
删除:poll()
判断队首:peek()<br>
阻塞等待
添加:put()<br>
删除:take()<br>
超时等待
添加:offer()
删除:pool()
双端队列:Deque<br>
Map
HashMap
Collections.synchronizedMap<br>
ConcurrentHashMap<br>
常用辅助类<br>
CountDownLatch<br>
构造器 CountDownLatch(int index); // index 为计数器初始值<br>
原理<br>
CountDownLatch.DownLatch(); //计数器减一<br>
CountDownLatch.await;当计数器为0时才开时向下执行<br>
CyclicBarrier
加法计数器
构造器:CyclicBarrier(int parties, Runnable barrierAction) //当计数器道道paryies后,执行barrierAction的内容
Semaphore<br>
线程通行证
构造器:Semaphore semaphore = new Semaphore(int index); // index为最大线程数
原理
semaphore.acquire(); 获得 ,假如线程已经满了,就等待有空位为止<br>
FixedThreadPool 和SingleThreadPool:允许请求队列的长度为Integer.MAX_VALUE,会堆积大量的请求,容易出现OOM异常<br>
semaphore.release();释放,会将当前的信号量释放 +1,然后唤醒等待的线程
ReadWriteLock<br>
写锁:一次只能被一个线程占用
创建锁:ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
上锁:readWriteLock.writeLock().lock();<br>
解锁:readWriteLock.writeLock().unlock();
读锁:可以被多个线程占用<br>
上锁:readWriteLock.readLock().lock();<br>
解锁:readWriteLock.readLock().unlock();
线程池
三大方法
Executors.newSingleThreadExecutor()<br>
只包含单个线程的线程池<br>
Executors.newFixedThreadPool(5)
自定义线程数量的线程池
Executors.newCachedThreadPool()
可伸缩的线程池
不推荐使用<br>
七大参数
corePoolSize:核心线程池大小<br>
maximumPoolSize:核心线程池最大核心数<br>
keepAliveTime:线程经过多久没被调用就被释放
TimeUnit:超时单位<br>
BlockingQueue<Runnable>:消息队列
ThreadFactory:线程工厂
RejectedExecutionHandler:拒绝策略
四种拒绝策略
AbortPolicy
抛出异常
java.util.concurrent.RejectedExecutionException
CallerRunsPolicy
不会抛出异常
队列满了,从哪来去哪里执行
DiscardOldestPolicy
不会抛出异常
队列满了尝试去和最早创建的线程竞争
竞争失败不执行
DiscardPolicy
不会抛出异常
队列满了不执行多出的
自定义创建线程池<br>
不能使用Executors去创建线程池
创建线程要使用ThreadPoolExecutor<br>
Executors返回的线程池的弊端
FixedThreadPool 和SingleThreadPool<br>
CachedThread和ScheduledThreadPool<br>
JMM
什么是JMM
Java内存模型,不存在的东西,概念,约定。
JMM同步约定
线程解锁前,必须把共享变量立即刷回主存<br>
线程加锁前,必须读取主存中的最新值到工作内存中
加锁核解锁必须是同一把锁
JMM八种指令
lock(锁定):作用于内存的变量,把一个变量标识为线程独占状态
unlock(解锁):作用域主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
read(读取):作用与工作内存的变量,它把一个变量的值从主内存中传输到线程的工作内存中,以便随后的load动作使用<br>
load(载入):作用域工作内存的变量,它把read操作从主内存中的变量放入工作内存中<br>
use(使用):作用域工作内存中的变量,它把工作内存的变量传输给执行引擎,每当虚拟机遇到一个需要使用到变量的值,就会使用到这个 指令<br>
assign(赋值):作用域工作内存中的变量,它把一个从执行引擎中接受到的值放入工作内的变量副本中<br>
store(存储):作用域主内存中的变量,它把一个从工作内存中一个变量的值传送到主内存中,一边后续的write使用<br>
write(写入):作用域主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中
JMM八种指令使用规则<br>
不允许read和load、store和write操作之一单独出现。几使用了read必须load,使用了store必须write<br>
不允许线程丢弃它们最近的assign操作,即工作变量的数据改变了之后,必须告知主内存
不允许一个线程将没有assign的数据从工作内存同步回主内存
一个新的变量必须再主内存中诞生,不允许工作内存直接使用一个违背初始化的变量,就是对变量实施use,store操作之前必须经过assign和load操作<br>
一个变量同一时间只有一个线程能对其进行lock。多次lock后,必须执行相同数的unlock才能解锁<br>
如果对一个变量进行lock操作,会情况所有工作内存中此变量的值,再执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值<br>
如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量<br>
对一个变量进行unlock操作之前,必须把此变量同步回主内存
JMM工作流程
子主题<br>
基础
创建线程的方法
继承Thread类
实现Runnable接口
实现Collable接口
使用线程池
线程的基本方法
getName():获取当前线程的名字
join():其他线程阻塞直至该线程执行完毕<br>
sleep(int):使该线程睡眠毫秒数
yeild():让出cpu,让cpu重新调度<br>
getPriority():返回该线程的优先级<br>
getState():返回该线程的状态
stop():线程停止--已废弃!<br>
线程状态
NEW :新生状态
RUNNABLE:运行状态<br>
BLOCKED:被阻塞等待监视器锁定的线程处于此状态<br>
WAITING:正在等待另一个线程执行特定动作的线程处于此状态<br>
TIMED_WAITING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态<br>
TERMINATED:已退出的线程处于此状态<br>
线程优先级
线程优先级范围:1-10;默认值:5
线程优先级<br>
Thread . MIN_PRIORITY = 1<br>
Thread . NORM_PRIORITY = 5<br>
Thread . MAX_PRIORITY = 10
设置线程优先级:Thread.setPriority();<br>
锁
synchronized
锁的对象
一个类<br>
一个对象
一个Class
常量
会引发的问题
一个线程持有锁会导致其他所有需要此锁的线程挂起
在多线程竞争下,加锁,释放锁辉当值比较多的上下文切换和调度延时,引起性能问题<br>
一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题<br>
Lock
synchronized与Lock区别
Synchronized 是内置的java关键字,Lock 是一个java类<br>
Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁<br>
Synchronized 会自动释放锁,Lock 必须要手动解锁,如果不释放会死锁<br>
Synchronized 线程1(获得锁,阻塞),线程2(等待,一直等),Lock锁就不一定会等待<br>
Synchronized 可重入锁,不可以判断的,非公平,Lock 可重入锁,可以判断锁,可以设置公平非公平锁<br>
Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码<br>
Callable<br>
Callable优点<br>
1.可以有返回值
2.可以抛出异常
Callable使用
创建一个线程: new Thread();
创建一个FutureTask对象:new FutureTask(myTread);<br>
启动线程:new Thread(futureTask).start();
四大函数式接口
Consumer
消费型接口
只有输入函数
没有输出函数
Function<br>
函数型接口
有一个输入参数
有一个输出参数
Predicate<br>
断定型接口
有一个输入参数
有一个只能为布尔类型的输出参数
Supplier<br>
供给型接口
没有输入参数
有一个输出参数<br>
ForkJoin
任务窃取
ForkJoinPool
ForkJoinTask
Votaile<br>
保证可见性
不保证原子性<br>
原子包装类<br>
AtomicBoolean<br>
AtomicInteger
AtomicLong<br>
指令重排<br>
你写的程序,计算机并不是按照你写的那样去执行的
处理器在进行指令重排的时候,考虑:数据之间的依赖性
CAS<br>
Unasfe<br>
Java无法操作内存
C++可以操作内存
Java可以通过Native调用C++操作内存<br>
Java可以通过Unasfe类操作内存
自旋锁
比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么执行操作,如果不是就一直循环
CAS缺点<br>
循环会耗时<br>
一次性只能保证一个共享变量的原子性<br>
存在ABA问题
AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题,Integer 在-128~127
子主题
0 条评论
下一页