java集合类哪些是有序的,哪些是无序的
实现了List接口的全部都是有序集合;ArrayList,LinkedList
实现了Set接口的,HashSet无序,TreeSet有序
实现了Map接口的,HashMap无序,TreeMap有序
List接口的主要对象:
----LinkedList没有同步方法;
----ArrayList是非同步的;
----Vector类似ArrayList,Vec是同步的(synchronized)
---------Stack(栈),push添加元素,pop取出元素,先进后出,search检查一个元素在堆栈中的位置。
Set不包含重复元素
----HashSet
----TreeSet(实现SortedSet接口,底层二叉树实现)【按自然升序排列,不保证出入一致】
----LinkedSet(底层链表实现)【保证出入一致】
Queen直接实现collection
Map
Map没有实现collection接口,提供key-value的映射规则
----hashmap 可空对象,非同步,效率高,
--------WeakHashMap:对key实行弱引用,如果一个key值不再被外部引用,它可以被GC回收
----hashtable 任何非空对象,同步的
-----TreeMap(实现SortedMap)有序的
总结:
----如果涉及到堆栈,队列(先进后出)等操作,应该考虑用List,如果需要快速插入删除元素,选用LinkedList,如果需要随机访问元素,选用ArrayList
----ArrayList、HashSet/LinkedHashSet、PriorityQueue、LinkedList是线程不安全的
ArrayList和Vector有什么区别
Vector是线程同步的,Vector扩容*2,ArrayList扩容*1.5
Comparable和Comparator区别
Comparable是一个接口,当调用collections.sort进行排序的时候,需要List内的对象都实现了Comparable接口
Comparator是排序规则,可以自定义排序规则来实现排序
Collections.sort(imageList, new Comparator() {
public int compare(Object a, Object b) {
int orderA = Integer.parseInt( ( (Image) a).getSequence());
int orderB = Integer.parseInt( ( (Image) b).getSequence());
return orderA - orderB;
}
});
双向链表相对于单向链表有什么优势
单向链表:由数据域和节点域组成,每一个节点的head指针指向下一个节点,这样就形成了单向链表;如果要查找其中某一个节点,只能从头开始遍历;
双向链表:双链表比单链表相比,多了一个指向尾指针(tail),双链表每个节点都有一个头指针(head)和尾指针(tail),双链表比单链表更容易操作,双链表节点的首节点(head)指向null,tail指向下一个节点的head,是双向关系。
单向链表:只有一个指向下一个节点的指针;
优点:单向链表增加删除节点简单,遍历的时候不会死循环
缺点:只能从头到尾遍历,只能找到后面一个节点,无法找到前面个
适用于节点的增加删除
双向链表:有两个指针,一个指向前一个节点,一个指向后一个节点
优点:可以找到前驱和后继,可进可退
缺点:增加删除节点复杂,多需要一个分配指针的空间
使用与需要双向查找的节点值得情况,适用于查询
Linux怎么查看cpu的使用率,怎么处理cpu过高
top:查看cpu使用率(进程级别 top -u oracle 即可查看oracle的cpu使用情况)
vmstat:系统级别的cpu使用情况
处理cpu跑高:top查看----p排序----ll /proc/PID/exe可以查看每个进程ID对应的程序文件----k PID终止进程
ps -ef|grep命令解释:
ps:将某个进程显示出来
grep:查找(文本搜索工具,可使用正则表达式)
|:管道命令,表示间ps grep同时执行
e:显示所有进程
f:全格式显示
netstat:检查Linux网络连接的工具
红黑树的原理:
红黑树是一种自平衡的二叉树
平衡是指所有叶子深度基本相同
二叉搜索树是指,节点最多两个儿子,且左子树节点都小于右子树
节点改动时,通过调整顺序(自旋),重新给节点进行染色,使节点满足某种特殊性质来保持平衡
插入、删除以及旋转、染色操作都是O(log n)的时间复杂度
满足以下基本性质:
----节点必须是红色或者黑色
----根节点和叶节点必须是黑色
----红色节点必须有两个黑色的儿子节点
----从任一节点出道到每个叶节点的路劲,黑色节点数量是相等的
关键属性:从根节点到最远的叶子节点的路径与到最近的叶子节点的路径长度不会超过2
保持平衡的原理:
参考文档:https://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html
ReentrantLock
实现Lock接口,可轮询,无条件的,定时的,可中断的
lock(),unlock()方法显示获取锁和释放锁,如果忘记释放锁会造成阻塞
可以使用tryLock()方法尝试获取锁,如果没有获取到则释放已经持有的锁,避免产生死锁
使用定时锁可以在一段时间内没有获取锁时可以返回,不会像内部锁一直阻塞
与synchronized的比较:
----ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
----synchronized是在jvm层面上实现的,可以通过监控工具进行监控,在代码出现异常的时候可以自动释放锁,但lock不行
----在资源竞争不激烈的情况下,synchronized的性能优于ReentrantLock,但竞争激烈的时候synchronized会下降很多,ReentrantLock会保持常态
结尾:写同步的时候,优先考虑synchronized(synchronized和ReentrantLock的开销差距在唤醒线程的数量,synchronized是唤醒锁池里的所有线程+刚好来访的线程,ReentrantLock是唤醒进来的第一个线程+刚好来访的线程;如果实在并发量不大的情况下,synchronized不需要将等待线程挂起,所以效率较高),如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。
ReentrantLock的特有能力:
----可以指定是公平锁还是非公平锁(先等待,先获取即为公平),synchronized为非公平锁
----ReentrantLock提供condition类,用来实现分组唤醒线程,synchronized为随机唤醒,或者全部唤醒
----ReentrantLock提供可以中断等待锁的线程机制,通过lock.lockInteruptibly()来实现
参考文档:https://blog.csdn.net/qq838642798/article/details/65441415
https://www.cnblogs.com/fanguangdexiaoyuer/p/5313653.html
悲观锁和乐观锁的区别:
悲观锁:假设最坏的情况,认为每个线程都会去修改数据,所以在每次拿到数据的时候都会上锁,别人只能等待知道持有锁的线程结束后再竞争锁(共享资源只能给一个线程使用),synchronized和ReentrantLock都是悲观锁,传统关系型数据库也基本是悲观锁(行锁,表锁,读写锁等)
乐观锁:认为每个线程都不会修改数据,但是在当前线程更新数据的时候回去判断是否有其他线程对数据进行更新,可以使用CAS算法和版本号机制实现(适用于多读类型的应用场景,提高吞吐量),java中atomic包下面的原子变量类就是乐观锁的CAS方式实现。
CAS算法(compare and swap):一种无锁算法,即在不使用锁的情况下实现多线程之间的变量同步(非阻塞同步),基本原理:首先读内存值V,确认进行比较的值A,需更新的值B;当且仅当内存值V等于A时,CAS通过原子方式用B值更新V值,否则不执行任何操作(自旋操作,即不成功会一直重试,知道成功,会造成cpu资源的严重浪费)。
乐观锁的缺点:
ABA问题:当前V值虽然等于A值,但是不保证在此过程中A值没有被改为其他值
循环开销过大:自旋操作会一直进行,直到成功(JVM支持cpu提供的pause命令可以提升一定的效率【延迟流水线作业,内存冲突会直接清空cpu流水线】)
只能保证一个共享变量的远在操作,当操作涉及多个共享变量的时候CAS无效,但是可以使用AtomicReference类来保证引用对象之间的原子性,将多个变量放在一个对象中进行操作
CAS和synchronized:
当资源竞争较少时,synchronized进行线程阻塞和唤醒切换线程操作会额外的浪费cpu资源,而CAS基于硬件实现,自旋概率小,不需要进入内核,不需要切换线程,因此可以获得更高的性能
当竞争较强时,CAS自旋的概率增大,从而浪费更多的资源,效率低于synchronized
综合比较:
性能:竞争小时:CAS >>>>>synchronized>>>>>ReentrantLock;竞争大时:ReentrantLock>>>>synchronized>>>>CAS
JavaSE 1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的 偏向锁 和 轻量级锁 以及其它各种优化之后变得在某些情况下并不是那么重了。synchronized的底层实现主要依靠 Lock-Free 的队列,基本思路是 自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。