【目录】
1.常用线程安全类型*
2.并发编程相关内容
3.并发编程经验总结*
4.并发编程常见面试题*
5.第8课总结回顾与作业实践
一 线程安全类型
基础数据类型与集合类
ArrayList
注意ArrayList在删除时应该从尾至头删除,因为从头删除会有元素位置移动,产生异常
LinkedList
线程安全的方法
CopyOnWriteArrayList
写操作
删除元素
读
HashMap
注意:升级版本时Key的顺序可能会发生变化,比如原系统使用Key-Value拼接成Redis的缓存key,由于升级而导致Key顺序变化,原来key找不到
LinkedHashMap
基本特点:继承自 HashMap,对 Entry 集合添加了一个双向链表
用途:保证有序,特别是 Java8 stream 操作的 toMap 时使用
原理:同 LinkedList,包括插入顺序和访问顺序
安全问题:
同 HashMap
ConcurrentHashMap-Java7 分段锁*
分段锁
- 默认16个Segment,降低锁粒度
- concurrentLevel = 16
想想:
Segment[] ~ 分库
HashEntry[] ~ 分表
ConcurrentHashMap-Java8
Java 7为实现并行访问,引入了Segment 这一结构,实现了分段锁,理论上最大并发度与 Segment 个数相等。
Java 8为进一步提高并发性,摒弃了分段锁的方案,而是直接使用一个大的数组
小结
二 并发编程
线程安全操作利器 - ThreadLocal
并行Stream
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
IntStream.range(1, 10000).forEach(i -> list.add(i));
BlockingQueue<Long> blockingQueue = new LinkedBlockingQueue(10000);
List<Long> longList = list.stream().parallel()
.map(i -> i.longValue())
.sorted()
.collect(Collectors.toList());
// 并行
longList.stream().parallel().forEach(i -> {
try {
blockingQueue.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("blockingQueue" + blockingQueue.toString());
}
伪并发问题
- 跟并发冲突问题类似的场景很多
- 比如浏览器端,表单的重复提交问题
++ 1、客户端控制(调用方),点击后按钮不可用,跳转到其他页
++ 2、服务器端控制(处理端),给每个表单生成一个编号,提交时判断重复
分布式下的锁和计数器
- 分布式环境下,多个机器的操作,超出了线程的协作机制,一定是并行的
- 例如某个任务只能由一个应用处理,部署了多个机器,怎么控制
- 例如针对用户的限流是每分钟60次计数,API 服务器有3台,用户可能随机访问到任何
一台,怎么控制?(秒杀场景是不是很像?库存固定且有限。)
三 经验总结
经验
- 粒度
- 性能
- 重入
- 公平
- 自旋锁(spinlock)
- 场景: 脱离业务场景谈性能都是耍流氓
线程间协作与通信
四 面试题
(自己总结)
五 总结
- 常见线程安全类型
- 并发编程
- 经验总结
- 并发面试题