java.util.concurrent.*(并发工具类) 学习笔记

java.util.concurrent.*(并发工具包) 学习笔记1.并发工具类的作用 1. 为了并发安全; 2. 方便线程管理,避免大量锁的创建和销毁,提高运行效率; 3. 线程间协作2. 线程池线程池的重要性 1. 反复创建线程与销毁大量的线程开销大 2. 过多的线程会占用太多的时间线程池的好处 1. 合理利用CPU和内存 2. 方便统一管理线程 3. 避免锁的创建和销毁,加快响应速度线程池的构造函数重要参数 1. corePoolSize : 核心线程池线程数量
摘要由CSDN通过智能技术生成

java.util.concurrent.*(并发工具包) 学习笔记

1.并发工具类的作用

	1. 为了并发安全;
	2. 方便线程管理,避免大量锁的创建和销毁,提高运行效率;
	3. 线程间协作

2. 线程池

线程池的重要性
	1. 反复创建线程与销毁大量的线程开销大
	2. 过多的线程会占用太多的时间
线程池的好处
	1. 合理利用CPU和内存
	2. 方便统一管理线程
	3. 避免锁的创建和销毁,加快响应速度
线程池的构造函数重要参数
	1. corePoolSize : 核心线程池线程数量
	2. maxPoolSize : 线程池最大线程数量
	3. keepAliveTime : 闲置线程生存时间, 当线程多余corePoolSize, 如果多余的线程空闲时间超过keep AliveTime,则线程被终止。
	4. workQueue : 任务等待队列
	5. threadFactory : 线程工厂
	6. handler : 拒绝任务策略
线程池工作原理
	当一个任务提交给线程池时,
	 1. 线程池首先判断线程池中线程数量是否小于corePoolSize, 如果小于corePoolSize, 则线程池新建新的线程执行任务;如果大于或等于corePoolSize, 则进入步骤2
	 2. 当前线程数目等于或大于corePoolSize, 则判断工作队列是否已满,如果未满,则将任务存入工作队列;如果已满,则进入步骤3
	 3. 线程池判断线程池中的线程是否都处于工作状态,如果没有,创建线程执行任务,如果已经满了,则交给拒绝任务策略handler处理此任务。

在这里插入图片描述

饱和策略
	1. AbortPolicy : 直接抛出异常
	2. CallerRunsPolicy : 有调用者执行线程
	3. DiscardOldestPolicy : 丢弃队列中最近的一个任务,并执行当前任务
	4. DiscardPolicy : 不处理,直接丢弃
Future接口
	Future接口和其实现类用来表示异步计算的结果
Future<String> future = executorService.submit(new CallableThreadPoolTest());
Runnable接口 和Callable接口
	都可以被ThreadPoolExecutor执行,它们之间的区别在于Runnable 不会返回结果,而Callable可以返回结果
常见的ThreadPoolExecutor
	1. FixedThreadPool : 使用(无界队列)LinkedBlockingQueue
	2. SingleThreadPool : corePoolSize = 1 && maximumPoolSize = 1 ,使用LinkedBlockingQueue无界队列
	3. cachedThreadPool : 使用有界队列SynchronousQueue, keepAliveTime = 60s
	4. ScheduledThreadPoolExecutor : 无界队列,可以设置定期执行任务

3. ThreadLocal

ThreadLocal的作用:
	1. 让某个需要用到的对象在线程间隔离(每个线程都有自己的对象)
	2. 在任何方法种都可以轻松获取对象

4. 锁

为什么sychronized不够用
	1. 效率低 : 只有代码块执行完毕或者中断才会释放锁,不能设定超时,不能中断一个正在试图获得锁的过程
	2. 不够灵活 : 加锁和释放锁的时机单一,只有代码执行完毕或发生中断才会释放锁
	3. 无法知道是否成功获得锁
Lock的常用方法
	lock(), tryLock(), tryLock(long time, TimeUnit unit), lockInterruptibly(), unlock()
队列同步器(AQS)AbstractQueueSynchronizer
	使用一个int成员变量state表示同步状态,通过内置的FIFO队列完成获取线程的排队工作,state的更新是通过CAS实现
	队列是双向链表
重入锁
	重入锁表示能够支持一个线程对资源的重复加锁 ,通过更新state来实现重入锁。
读写锁 ReentrantReadWriteLock
	也是通过AQS实现,只不过是讲state按位划分都状态和写状态,高16位是读状态,低16位是写状态。
	读写锁降级是指由写锁降级成为读锁

5. 原子类

	通过CAS实现原子操作
	1. AtomicBoolean
	2. AtomicInteger
	3. AtomicLong
	4. AtomicIntegerArray
	5. AtomicReference : 原子引用类,只是引用不能更改,但其指向的类的内容是可以更改的
	6. AtomicIntegerFeildUpdater : 原子更新字段类, 如果需要原子的更新某个类里面的某个

6. CAS原理(Compare And Swap)

CAS存在的问题
	1. ABA问题,如果一个值由A变成B,然后再由B变成A,那么CAS检查的时候会发现值没有变,但实际变化了。ABA问题的解决思路是加版本号。
	2. 循环时间开销大 : 自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。
	3. 只能保证一个变量的原子操作

7. 并发容器

	1. ConcurrentHashMap
	2. ConcurrentLinkedQueue
	3. 阻塞队列(BlockingQueue)
HashMap不能用于并发
	HashMap在并发执行put操作时可能由于多线程导致HashMap的Entry链表形成环形链表,引起死循环.因为,一旦形成死循环,Entry的next节点永远不为空,就会产生死循环获取Entry.
	HashTable 使用Sychronized 来保证线程安全,其对整个Map进行加锁,所有线程必须竞争同一把锁, 效率低下. 
	ConcurrentHashMap采用锁分段技术,首先将数据分成一段一段存储,然后给每一段数据分配一把锁,当一个线程占用锁访问其中一个段的数据时,其他段的数据能被其他线程访问.
ConcurrentHashMap

在这里插入图片描述

ConcurrentLinkedQueue
	CAS 保证线程安全
阻塞队列(BlockingQueue)
	阻塞队列时一个支持两个附加操作的队列,这两个附加的操作支持阻塞的插入和移除方法.
	1.  支持阻塞的插入方法: 当队列满是,队列会阻塞插入元素的线程,知道队列不满
	2. 支持阻塞的移除方法: 当队列空时,获取元素的线程会等待队列变为非空
Java里的阻塞队列
	1. ArrayBlockingQueue : 一个由数组结构组成的有界阻塞队列
	2. LinkedBlockingQueue : 一个有链表结构组成的有界阻塞队列
	3. PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列
	4. DelayQueue :  一个支持优先级排序的无界阻塞队列
	5. SychronousQueue : 一个不存储元素的阻塞队列
	6. LinkedTransferQueue : 一个由链表结构组成的无界阻塞队列
	7. LinkedBlockingDeque	 : 一个由链表结构组成的双向阻塞队列

8. AQS(AbstratQueuedSynchronizer)

	核心数据结构 state + 双向链表   其中state用volatile修饰
	底层的操作时CAS + 自旋
	AQS提供两种资源共享方式: 独占和共享
	主要方法: acquire()
			tryAcquire()
			addWaiter()
			release()

在这里插入图片描述

9. Java 并发控制工具类

并发工具类
	1. Semaphore
CountDownLatch
	说明 : 用于倒数结束之前,使当前线程一直处于等待状态,直到倒数结束,此线程才继续工作
	主要方法: 构造方法 CountDownLatch(10); // 指定倒计数的大小
			latch.await();  // 是当前线程处于等待,当latch倒计数结束后继续执行
			latch.countDown();  // 使倒计数减一。
	用法 : 1. 一个线程等待多个其他线程执行完毕再继续
			2. 多个线程等待一个线程执行完毕再继续

在这里插入图片描述
CountDownLatch实例代码

import java.util.concurrent.*;

/**
 * @Author : suyc
 * @Date : 2020/6/19  9:37
 * @Descriptions : 测试一个完整的跑步比赛过程
 */
public class CountDownLatchTest12 {
   
    public static void main(String[] args) throws InterruptedException {
   
        // 定义运动员数量
        int num = 10;
        // 定义开始时裁判员,在所有选手准备完毕后发起信号枪
        CountDownLatch begin = new CountDownLatch(1);
        // 定义终点裁判员,直到所有选手都到达终点宣布比赛结束
        CountDownLatch end = new CountDownLatch(num);

        ExecutorService executorService = Executors.newFixedThreadPool(num);
        for(int i = 0; i < num; i ++){
   
            final int no = i + 1;
            Runnable athlete = new Runnable(){
   
                @Override
                public void run(){
   
                    try {
   
                        System.out.println("No " + no + "开始准备");
                        Thread.sleep((long)(Math.random() *
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值