java并发包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3osfRXtS-1612353712348)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210203155329540.png)]
Java.util.concurrency
锁机制Locks:Lock,condition,ReadWriteLock
原子操作类Atomic:Atomicinteger
线程池相关类Execter:Future,Callable,Executor
信号量三族工具类Tools:CountDownLatch,CyclicBarrier,Semaphore
并发集合类Collections:CopyOnWriteArrayList,ConcurrentMap
锁*
lock:
改进了之前的notify,lock(),unlock()显性加锁和解锁,并且加了一些获取锁的方法,尝试一段时间,尝试一次或者拿到后允许中断。并且引入了condition,绑定到当前锁的条件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mT0u7jWK-1612353712350)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210203161504541.png)]
ReadWriteLock:
重要方法 | 说明 |
---|---|
Lock readLock() | 获取读锁,共享锁 |
Lock writeLock() | 获取写锁,独占锁 |
构造方法
public ReetrantReadWriteLock(boolean fair)
{
sync = fair?newFairSync():new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
说明:
读锁可以被多个线程持有,以保证数据可见。
写锁锁是一个独占锁,只能被一个线程持有,以保证线程安全。
适合读多写少的情况。
LockSupport—锁当前线程
线程的静态方法,可以直接调用以控制当前线程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kXlCWJzU-1612353712352)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210203164839327.png)]
可以类比于 await sleep
方法unpark()是一个线程
并发原子类*
原子类工具包 : java.util.concurrent.atomic 下有一些支持原子操作的类
AtomicInteger 示例
pubulic class AtomicCounter(){
private AtomicInteger sum =new AtomicInteger(0);// 初值为零
public int incrAndGet(){
return sum.incrementAndGet();
}
public int getSum(){
return sum.get();
}
}
无锁技术 ——Atomic工具类
- Unsafe API Compare And Swap
- CPU指令支持:CAS指令
#volatile保证读写皆可见
#使用CAS指令,作为乐观锁自旋写入
LongAdder对AtomicLong的改进
改进思路——多路归并
- AtomicInteger和AtomicLong中的value是所以线程竞争的热点数据
- 将value拆分成和线程一样多的数组Cell[];
- 每个线程写自己的Cell[i]++;最后对数组进行归并。
- 也不在需要CAS和乐观锁自旋了
并发工具类详解*
关于线程之间的协作,锁的机制是一种比较裸的机制,较为简单粗暴。
AQS(AbstractQueuedSynchronizer)
队列同步器,java并发包最核心的东西,构建锁和其他同步组件的基础。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8nCSuB5a-1612353712355)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210203190809419.png)]
Semaphore——信号量
- 准入数量N
- 准入数量为零时等价于独占锁
实例代码
对读写锁的一种实现,此方法对读进行了限流
public class SemphoreCounter{
private int sum= 0;
//定义一个读锁,允许100个来读
private Semaphore readSemaphore =new Semaphore(100,true);
//定义一个写锁,只允许一个
private Semaphore writeSemphore =new Semaphore(1);
public int incrAndGet(){
try{
writeSemaphore.acqurieUninterruptibly();
return ++sum;
}finally{
writeSemaphore.release();
}
}
public int get(){
try{
readSemaphore.acqurieUninterruptibly();
return sum;
}finally
readSemaphore.release();
}
}
CountDownLatch
重要方法 | 说明 |
---|---|
public CountDownLatch(count) | 构造方法(总数) |
void await()throw InterruptedException | 等待 数量归零 |
boolean await(long timeout ,TimeUnit unit) | 限时等待 |
void countDown() | 等待数量减1 |
long getCount() | 返回剩余数量 |
示例代码
//任务线程,这个线程每次创建并执行都会调用Latch的 countDown()方法一次。
public static Class CountDownLatchTask implements Runable{
private CountDownLatch Latch;
public CountDownLatchTask( CountDownLatch Latch){
this.latch=latch;
}
@Override
public void run(){
Integer mills =new Random().nextInt(10000);
try{
TimeUnit.MILLISECONDS.sleep(mills);
this.latch.countDown();
system.out.println("我的任务OK:"+Thread.currentThread().getName());
}catch(Exception e){
e.printStackTrace();
}
}
}
//主方法
public static void main(String[] args) throw Exception{
int num = 100;
CountDownLatch Latch =new CountDownLatch(num);
List<CompeletableFuture>list =new ArryList<>(num);
for(int i=0;i<num;i++){
CompletableFuture<void> future =CompetablFuture.runAsync(new CountDownLatch(latch))
list.add(future);
}
}
latch.wait();
for(CompletableFuture future : )
future.get();
}
future =CompetablFuture.runAsync(new CountDownLatch(latch))
list.add(future);
}
}
latch.wait();
for(CompletableFuture future : )
future.get();
}