April 6, 2017
1. 线程状态 # state 状态 说明 New 新建 新创建了一个线程对象,还未调用线程的 start() 方法 Runnable 就绪 线程对象创建后,其他线程调用了该对象的 start() 方法,该状态的线程位于可运行线程池中,变得可运行,等待获取 CPU 的使用权 Running 运行 就绪状态的线程获取了 CPU,执行程序代码的状态,还有种可能就是这个线程正在等待其他的系统资源(IO 资源等),这种状态也称为 Running 状态 Blocked 阻塞 一个线程因为等待监视锁而被阻塞的状态,也称之为阻塞状态。阻塞的线程不会被分配 CPU 资源 WAITING 等待 一个正在等待的线程的状态,也称之为等待状态 TIMED_WAITING 超时等待 一个在限定时间内等待的线程的状态。也称之为限时等待状态 Dead 死亡 线程执行完了或者因异常退出了 run() 方法,该线程结束生命周期 (当时如果线程被持久持有,可能不会被回收) 注意:
WAITING: 造成线程等待的原因有三种,分别是调用 Object.wait()、join() 以及 LockSupport.park() 方法。处于等待状态的线程,正在等待其他线程去执行一个特定的操作。例如:因为 wait() 而等待的线程正在等待另一个线程去调用 notify() 或 notifyAll();一个因为 join() 而等待的线程正在等待另一个线程结束。处于等待状态的线程不会被分配 CPU 资源。 TIMED_WAITING: 造成线程限时等待状态的原因有五种,分别是调用 Thread.sleep(long)、Object.wait(long)、join(long)、LockSupport.parkNanos(obj,long) 和 LockSupport.parkUntil(obj,long)。 2. 线程状态转换 #
April 4, 2017
Happens-Before 规则 # 规则 说明 单一线程原则 在一个线程内,在程序前面的操作先行发生于后面的操作 管程锁定规则 一个 unlock 操作先行发生于后面对同一个锁的 lock 操作 volatile 变量规则 对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作 线程启动规则 Thread 对象的 start() 方法调用先行发生于此线程的每一个动作 线程加入规则 Thread 对象的结束先行发生于 join() 方法返回 线程中断规则 对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过 interrupted() 方法检测到是否有中断发生 对象终结规则 一个对象的初始化完成 (构造函数执行结束) 先行发生于它的 finalize() 方法的开始 传递性 如果操作 A 先行发生于操作 B,操作 B 先行发生于操作 C,那么操作 A 先行发生于操作 C 参考文献 # Java 并发 - 理论基础
March 3, 2017
WeakHashMap 的特殊之处在于 WeakHashMap 里的 entry 可能会被 GC 自动删除,即使程序员没有调用 remove() 或者 clear() 方法。
...
February 28, 2017
TreeMap 实现了 SortedMap 接口,也就是说会按照 key 的大小顺序对 Map 中的元素进行排序,key 大小的评判可以通过其本身的自然顺序 (natural ordering),也可以通过构造时传入的比较器 (Comparator)。
...
February 13, 2017
LinkedHashMap 是 HashMap 的直接子类,二者唯一的区别是 LinkedHashMap 在 HashMap 的基础上,采用双向链表 (doubly-linked list) 的形式将所有 entry 连接起来,这样是为保证元素的迭代顺序跟插入顺序相同。
...
February 10, 2017
1. 底层数据结构 # Java 1.7 中使用数组+链表这样的数据结构,自 Java 1.8 开始使用数组+链表+红黑树这样的数据结构。
2. 数组扩容 # resize() 方法用于初始化数组或数组扩容,每次扩容后,容量为原来的 2 倍,并进行数据迁移。
3.线程不安全 # HashMap 的线程不安全主要体现在下面两个方面:
在 Java 1.7 中,当并发执行扩容操作时会造成环形链。
这里主要的原因是线程1上线文中保存的指针指向的数据(newtable,临界资源)被线程2做了修改,当线程1重新恢复上线文后,在已经被修改的数据(newtable,临界资源)上继续未完成的操作,最终导致结果不符合预期。
在 Java 1.8 中,在并发执行 put 操作时会发生数据覆盖的情况。
4. 参考文献 # HashMap为什么在多线程操作下不安全(jdk1.7和jdk1.8原因不同)
February 5, 2017
优先队列的作用是能保证每次取出的元素都是队列中权值最小的,这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序,也可以通过构造时传入的比较器 Comparator。
...
January 31, 2017
Java 里有一个叫做 Stack 的类,却没有叫做 Queue 的类 (它是个接口名字)。当需要使用栈时,Java 已不推荐使用 Stack,而是推荐使用更高效的 ArrayDeque;既然 Queue 只是一个接口,当需要使用队列时也就首选 ArrayDeque 了 (次选是 LinkedList)。
...
January 23, 2017
LinkedList 同时实现了 List 接口和 Deque 接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列 (Queue),同时又可以看作一个栈 (Stack)。所以当需要使用栈或者队列时,可以考虑使用 LinkedList。
...
January 20, 2017
ArrayList 实现了 List 接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入 null 元素,底层通过数组实现。除该类未实现同步外,其余跟 Vector 大致相同。
...