从6月22起,利用空闲的几天时间,重新学习了下慕课网上Jimin的《Java并发编程入门与高并发面试》,之前的课程名称应该是《Java并发编程与高并发解决方案》。顺便记录点笔记,如下:
第19章 课程总结20200629
第18章 高并发之高可用手段介绍 20200629
1.任务调度系统分布式:elastic-job + zookeeper
2.主备切换:apache curator + zookeeper 分布式锁实现
3.监控报警 手记:https://www.imooc.com/article/20891
第17章 高并发之数据库切库分库分表思路20200629
1.只有思路,具体实现看手记。
第16章 高并发之服务降级与服务熔断思路20200629
1.服务降级
处理不了了,给个默认的返回。
2.服务熔断
软件系统,过载,防止系统故障,保护措施
3.服务降级分类:
自动降级:超时、失败次数、故障、限流
人工降级:秒杀、双11大促
4.共性:目的、最终表现、粒度、自治
5.区别:触发原因、管理目标层次、实现方式
第15章 高并发之应用限流思路 20200624 讲的不好
资料:代码实现:https://blog.csdn.net/Victorgcx/article/details/104248819
1.常见限流:限制总并发数、限制瞬时并发数、 限制时间窗口内的平均速率
限制总并发数:通过配置数据库连接池、线程池大小来约束总并发数。
限制瞬时并发数:比如在入口层(nginx 添加nginx_http_limit_conn_module)l来限制同一个ip来源的连接数,防止恶意攻击访问的情况。
其他方式:限制远程接口的调用速率、限制mq的消费速率
2.应用限流=算法
计数器法:
滑动窗口:
漏桶:
令牌桶 token bucket:
第14章 高并发之应用拆分思路
1.拆分原则
业务优先
循序渐进
兼技术:重构、分层
可靠测试
2.思考
应用之间通信:RPC、消息队列
应用之间数据库设计:每个应用都有独立的数据库
避免事务操作跨应用
第13章 高并发之消息队列思路
1.【生产】 和 【消费】的速度活稳定性等因素不一致
2.好处:
业务解耦、最终一致性、广播、错峰与流控、
3.kafka
10w/s 吞吐
4.rabbitMQ
有界面。
第12章 高并发之缓存思路
12-4 缓存-高并发场景问题讲解.mp4
1.缓存一致性
2.缓存穿透=击穿
没有命中缓存,处于容错考虑,去数据库查询,但是空,高并发情况,导致发生很多不必要的查库。
A.缓存空对象、空集合null
B.单独处理
3.缓存雪崩现象
4.缓存高并发实战-股票分时线
12-3 缓存-redis的使用讲解-1
1.使用简单,略
12-1 缓存-特征、场景及组件介绍-1&2
1.缓存清空策略:FIFO、LFU、LRU,过期时间、随机等
2.缓存特征
3.缓存命中率影响因素
业务场景和业务需求、缓存的设计(粒度和策略)、缓存容量和基础设施
4.本地缓存 guava cache
5.分布式缓存 memcache、Redis
第11章 高并发之扩容思路
11.1 扩容思路讲解
1.垂直扩容:纵向扩展:提高系统部件能力
2.水平扩容 横向扩展:增加更多系统成员来实现
3.扩容-数据库
读操作扩展:memcache、redis、cdn等缓存
写操作扩展:Cassandra、Hbase等
第10章 多线程并发拓展 20200628
10-5 多线程并发与线程安全总结
1.
10-4 hashmap与concurrenthashmap解析
1.hashmap rehash 多想吃环境下会可能会发生死锁。
2.fas-fail通过抛出ConcurrentModificationException异常来触发的
3.java7 o(n) java8 节点数达到8时 使用红黑树 o(logn)
10-3 spring与线程安全
1.
10-2 并发最佳实践
1.使用本地变量
2.使用不可变类:降低代码中同步数量
3.最小化锁的作用域范围 S=1/(1-a+a/n)
4.使用线程池的Executor,而不是直接new thread执行
5.宁可使用同步也不要使用线程的wait和notify:
6使用BlockingQueue事项生产-消费模式
7.使用并发集合而不是加了锁的同步集合
8.使用semaphore创建有界的访问:
9.宁可使用同步代码块,也不是用同步
10-1 死锁
1.必要条件
互斥条件、请求和保持条件、不剥夺条件、环路等待
第9章 线程调度-线程池 20200628
9-1&2&3 线程池
1.new Thread 弊端
每次新建对象,性能差
线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能过多占用资源导致死机或者oom
缺少更多功能,如更多执行、定期执行、线程中断
2.线程池的好处
重用存在的线程,减少对象创建、消亡的开销,性能佳
可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞
提供定时执行、定期执行,单线程、并发数控制等功能
3.ThreadPoolExcutor
keepAliveTime:线程数大于core数量时,如果没有新的任务提交,超过这个时间就会终止
rejectHandler:任务拒绝时的处理策略。
4.线程池的合理配置:
cpu密集型任务,就需要尽量压榨cpu,参考值可以设置为 NCpu+1
Io密集型任务,参考值可以设置为2*Ncpu
第8章 J.U.C组件拓展20200624
8-1&2 J.U.C-FutureTask-1&2
1.无新东西
8-3 J.U.C-ForkJoin 框架
1.注意多体会例子即可
8-4 J.U.C-BlockingQueue
1.
第7章 J.U.C之AQS 20200624
AQS原理
AQS:AbstractQuenedSynchronizer抽象的队列式同步器。是除了java自带的synchronized关键字之外的锁机制。
AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包
AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node),来实现锁的分配。
用大白话来说,AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。
**注意:AQS是自旋锁:**在等待唤醒的时候,经常会使用自旋(while(!cas()))的方式,不停地尝试获取锁,直到被其他线程获取成功
实现了AQS的锁有:自旋锁、互斥锁、读锁写锁、条件产量、信号量、栅栏都是AQS的衍生物.
7-1 J.U.C之AQS-介绍
1.AQS同步组件:countDownLatch、Semaphore、CyclicBarrier、ReentrantLock、Condition、FutureTask
7-2 J.U.C之AQS-CountDownLatch
1.countdown 方法 如果有异常最好放在finally中
2.await支持超时时间设置,超时不再等待;
7-3 J.U.C之AQS-Semaphore
1.控制并发访问的个数
2.可以一次获取多个许可;
7-4 J.U.C之AQS-CyclicBarrier
1.reset 可以重复使用
2.各个线程相互等待的关系,countdowlatch 一个等其他多个。
3.支持创建 new CyclicBarrier 时 传入一个runnable,屏障结束后,优先执行runnal中的内容,在执行 后面的continue
4.
7-5&6 J.U.C之AQS-ReentrantLock与锁-1&2
1.reentrantLock 和synchronizede区别
可重入性
锁的实现:synchronized是基于jvm实现的,reentrant基于jdk实现(用户自己实现的)
性能的区别:
功能区别:
2.reentrantLock的独有的功能
可指定是公平锁还是非公平锁,synchronizede非公平锁
提供了一个condition类,可以分组唤醒需要唤醒的线程
提供能够中断等待锁的线程的机制,lock.lockInterruptibly()
3.reentrantReadWriteLock
没有任何读写锁的时候才能取得写锁
4.StampedLock
写读、乐观读
对吞吐量有巨大的改进,尤其是在读 线程越来越多的情况。
A.所有获取锁的方法,都返回一个邮戳(Stamp),Stamp为0表示获取失败,其余都表示成功;
B.所有释放锁的方法,都需要一个邮戳(Stamp),这个Stamp必须是和成功获取锁时得到的Stamp一致;
C.StampedLock是不可重入的;(如果一个线程已经持有了写锁,再去获取写锁的话就会造成死锁)
D.StampedLock有三种访问模式:
①Reading(读模式):功能和ReentrantReadWriteLock的读锁类似
②Writing(写模式):功能和ReentrantReadWriteLock的写锁类似
③Optimistic reading(乐观读模式):这是一种优化的读模式。
E.StampedLock支持读锁和写锁的相互转换
我们知道RRW中,当线程获取到写锁后,可以降级为读锁,但是读锁是不能直接升级为写锁的。
StampedLock提供了读锁和写锁相互转换的功能,使得该类支持更多的应用场景。
F.无论写锁还是读锁,都不支持Conditon等待
5.condition
是一个条件类,维护了一个等待信号的队列。
是一个多线间协调通信的工具类,使得某个类或者线程等待某个条件,只有该提交具备,该线程被唤醒。
第6章 线程安全策略
6-1&2 不可变对象-1&2
1.final关键字:类、方法、变量
修饰类:不能被继承
修饰方法:1.锁定方法不能被继承类修改 2效率
修饰变量:基本数据类型变量、引用类型变量
2.Collections.unmodifiableXXX:Collection 、List、Set、Map。。。
Guava:ImmutableXXX :Collection 、List、Set、Map。。。
6-3&4 线程封闭-1&2—threadLocal的使用
1.ThreadLocal线程封闭:特别好的封闭方法 例子:数据库connection对象
2.局部变量线程封闭的。
6-5&6 线程不安全类与写法-1&2
1.stringbuilder 线程不安全 Stringbuffer 线程安全。
2.SimpleDateFormat 线程不安全,如果使用 放在方法里每次声明一个使用。
3.org.joda.time.format.DateTimeFormatter 线程安全。
4.ArrayList、HashSet、HashMap 均线程不安全类
6-7&8 同步容器-1&2 性能不好,并不能保证线程安全
1. Collections.synchronizedXXX线程安全
2.
6-9 并发容器及安全共享策略总结
1.ArrayList->CopyOnwriteArrayList
2.HashSet->CopyOnWriteArraySet
TreeSet->CopyOnwriteSkipListSet
3.HashMap->ConcurrentHashMap
TreeMap->ConcurrentSkipListMap 并发度高时,对键值排序时最好使用此 map
第五章 安全发布对象-本章主要是单例的各种写法
5-2 安全发布对象-四种方法-1
1.在静态函数中初始化一个对象引用
单例模式的实现
双重检测机制 加volatile关键字
枚举的写法
2.将对象的引用保存到volatile类型域或者atomicReference对象中
3.将对象的引用保存到某个正确构造对象的final类型域中
4.将对象的引用保存到一个由锁保护的域中
5-1 安全发布对象-发布与逸出
1.发布对象:是一个对象能够被当前范围之外的代码所使用
对象溢出:一种错误的发布,当一个对象还没有构造完成时,就使它被其他线程所见。
第四章 线程安全性 20200623
总结:
happens-before:重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)。
八种原则。
4-4 线程安全性-可见性
1.jvm关于synchronizede的两条规定
线程解锁前,必须把共享变量的最新值刷新到主内存
线程加锁时,将清空工作内存中的共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意,加锁和解锁是同一把锁)
2.volatile
通过加入内存屏障和禁止重排序 优化 来实现
4-3 线程安全性-原子性-synchronized---- SyncronizedExample2.java
1.syncronized 修饰代码块、方法,作用于调用的对象
修饰静态方法、修饰类,作用于所有对象
4-1 线程安全性-原子性-atomic-1& c2
1. AtomicReference 、 AtomicIntegerFieldUpdater
2.AtomicStampReference :CAS的 ABA问题
第三章 项目准备 20200623
3-4 并发模拟-代码
1.
3-3 并发模拟-工具
1.postman 环境设置以及并发数量的测试
2.jmeter的使用
3.ab的使用
3-1 案例环境初始化
第二章 并发基础 20200622
2-3 JAVA内存模型
1.规范:java虚拟机和计算机内存如何协同工作,规定了一个线程如何和何时 可以看见其他线程修改过的共享变量的值,以及在必须时 如何同步的 访问共享变量。
2-2 CPU多级缓存-乱序执行优化
1.
2-1
1.cpu cache 有什么意义
时间局部性:如果某个数据被访问,那么在不就的将来它很可能被再次访问
空间局部性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问
2.cpu多级缓存-缓存一致性(MESI)
用于保证多个cpu cache之间缓存贡献数据的一致
1-3 并发与高并发基本概念
1.
1-2并发编程初体验
1.200个线程 累加例子
2.
1-1整体介绍 过