泛型的学习
1.是什么
集合中存储对象,防止了类型转换的繁琐步骤, 避免了在运行时出现ClassCastException。
2.如何工作的
类型擦除,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息;
3. 泛型的使用
- 限定通配符, <? extends T>,<? super T>
- 非限定通配符<?>可以用任意类型来替代
- Array,中不可以使用泛型;
容器的学习
设计模式
- 迭代器模式,list通过,Iterable,实现迭代;
- 适配器模式,Arrays.asList,通过转化Arrays为LIst;
ArrayList分析
- 初始大小为10
- 扩容1.5倍,Arrays.copyOf(),
oldCapacity + (oldCapacity >> 1)
- 删除同样, 复杂度O(n)
- Fail-Fast,modCount记录结构变化次数, 迭代序列化情况下,比较操作前后的modCount,如果改变就抛出,ConcurrentModificationException
- 序列化, transient修饰则不会被序列化;
Vector
区别:
- vector 是同步的
- 扩容为两倍;
替代方案
-
Collections.synchronizedList();
-
CopyOnWriteArrayList
- 读多写少,
- 内存占用, 数据不一致
HashMap
链表数组,数组中每个格都是链表, 遇到hash冲突,就将冲突加到链表中;
-
transient Entry<k,v>[] table;
链表类型的数组
-
拉链法来解决冲突,同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry(除留余数法)
三种解决hash冲突的方法:
1. 拉链法,
1. 计算键值对所在的桶;
2. 链表上顺序查找
2. 散列地址法
1. 线性,二次,伪随机法
3. 再hash法;
HashMap分析
- 大小默认是16
- 1.8以后,Table默认大小不小于64,链表长度等于8的时候转化为红黑树; 不使用头插法;
ConcurrentHashMap
-
segement分段,默认16,里面记录包含的kv数;
-
size操作只需统计segement中count包含的 kv对数;默认尝试三次;
并发
线程状态
- 新建,
- 可运行
- 阻塞
- 无限等待
- 限期等待:阻塞, 和睡眠;
- 死亡
使用
- 实现 Runnable 接口;
- 实现 Callable 接口;
- 继承 Thread 类。start启动重写run()方法的线程
线程基础机制
- Executor
主要有三种 Executor:
- CachedThreadPool:一个任务创建一个线程;
- FixedThreadPool:所有任务只能使用固定大小的线程;
- SingleThreadExecutor:相当于大小为 1 的 FixedThreadPool。
-
Daemon
守护线程是程序运行时在后台提供服务的线程
-
Sleep
休眠当前线程,可能抛出interruptedException
-
yield
建议同等优先级的其他线程运行
中断
interrupt
interepted
互斥同步
- synchronized
- ReentrantLock
比较
1. 锁的实现
synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。
2. 性能
新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。
3. 等待可中断
当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
ReentrantLock 可中断,而 synchronized 不行。
4. 公平锁
公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。
synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。
5. 锁绑定多个条件
一个 ReentrantLock 可以同时绑定多个 Condition 对象。
无同步方案
- 栈封闭:同一方法的局部变量,位于虚拟机栈中, 属于线程私有;
- 线程本地储存(Thread Local Storage):web应用中, ThreadLocal, 实现线程本地储存功能;
- 可重入代码: 不依赖存储在堆上的数据和公用的系统资源、用到的状态量都由参数中传入、不调用非可重入的方法等。
JUC AQS
-
CountDownLatch
维护了一个计数器 cnt,每次调用 countDown() 方法会让计数器的值减 1,减到 0 的时候,那些因为调用 await() 方法而在等待的线程就会被唤醒。
-
CyclicBarrier
和 CountdownLatch 相似,都是通过维护计数器来实现的。线程执行 await() 方法之后计数器会减 1,并进行等待,直到计数器为 0,所有调用 await() 方法而在等待的线程才能继续执行。
- Semaphore
Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的访问线程数。
- FutureTask
- BlockingQueue
- FIFO 队列 :LinkedBlockingQueue、ArrayBlockingQueue(固定长度)
- 优先级队列 :PriorityBlockingQueue
锁优化
- 轻量级锁
- 自旋锁
- 锁消除
- 锁粗化
- 偏向锁
java内存模型
主内存工作内存
缓存一致性:加入高速缓存来提高线程读写;
内存间交互
八个操作
- read:把一个变量的值从主内存传输到工作内存中
- load:在 read 之后执行,把 read 得到的值放入工作内存的变量副本中
- use:把工作内存中一个变量的值传递给执行引擎
- assign:把一个从执行引擎接收到的值赋给工作内存的变量
- store:把工作内存的一个变量的值传送到主内存中
- write:在 store 之后执行,把 store 得到的值放入主内存的变量中
- lock:作用于主内存的变量
- unlock
内存三大特性
-
原子性,操作的原子性;
- 原子类 AtomicInteger等
- synchronized
- 它对应的内存间交互操作为:lock 和 unlock,
- 在虚拟机实现上对应的字节码指令为 monitorenter 和 monitorexit。
-
可见性
-
有序性
- volatile通过添加内存屏障禁止指令重拍
- synchronized保证每个时刻只有一个线程在执行