Java,
Java,
- 有个奇葩的点 ,HashTable里
区别只是能否remove而已, 这个设计不知道在干啥。
而HashMap 用了KeyIterator 和 ValueIterator 分开处理 ,HashTable用的是一个 ,区别了type而已
-
HashMap 长度为什么必须是2的倍数?
这是核心的get方法, 存的时候 ,Node是个数组,数组的角标 就是通过 length-1 & hash来的, 然而直接用存放数据的hash来算,数组长度一般都比较小,这样**&**出来的数据 碰撞就太容易发生了,所以HashMap自己实现了一个hash()
右移16位, 就是取高16位 ,减少了碰撞的可能。 -
ConcurrentHashMap 已经优化到不用Segment了 , 用volatile 的sizeCtl 实现互斥控制 ,put的同步用sychronize实现 , 用了大量的Unsafe包的CAS操作
-
Java 8 以后 Interface 是可以有方法实现的 !
11. Monitor是对象同步的基本单元 , sychronize 在Java早期(6以前),Monitor的实现完全靠操作系统的互斥锁,这里涉及到了操作系统的两种操作级别,分权限的高低,因为内核原因, 比较耗费资源 ,设置 对象头中的Mark Word
-
JVM 内存区域划分
程序计数器
存储当前线程的当前方法的JVM指令地址
Java虚拟机栈
每个线程在创建的时候都会创建一个虚拟机栈,调用一次方法,新建一个栈帧,JVM负责出栈和入栈
栈中存放局部变量表,动态链接,方法正常或者异常退出的定义堆(所有线程共享)
存放对象实例, 会被不同的垃圾回收器划分,如 新生代 老年代
方法区 (所有线程共享)
存储元数据:类结构体 、对应的运行时常量池 字段 方法代码等 ,故在永久代于Jdk8弃用后,增加了元数据区。
运行时常量池
在方法区里,包括 版本号、字段、方法、超类、常量池
本地方法栈
类似于Java虚拟机栈, 支持本地方法的调用
-
volatile等 所谓的线程可见性,就是 内存屏障通过 强制刷出处理器缓存的方式 保证其他的线程拿到最新的值
-
JMM 实际上平衡了 jvm和cpu对性能的要求 和java层简单的安全
-
一段代码说明 可见性和 原子性区别:
试问: 如果去掉 sychronize 结果如何? 去掉volatile 结果如何? 去掉count的 static 结果如何??? -
所谓happen-bfore原则:
在多线程条件下 发生了指令重排序,在如图场景中,对 f 的判断就会出现问题, 所以要按照原则来。 -
java 的transient关键字,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
-
MySQL 数据隔离级别大概分四个:
-
读未提交 :一个事务能看到另一个事务未提交的状态, 容易脏读
-
读已提交 :事务看到的是已提交的状态, 也不会有脏读,但是允许并发,会发生 不可重复读和幻读
-
可重复读: 在一个事务中读取的 数据是一致的,MySQL默认的隔离级别。不一定出现幻读,要根据不同数据库实现
-
串行化: 并发事务是串行的,意味着要加锁了,也是 最高的隔离级别
脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问 这个数据,然后使用了这个数据。
不可重复读:一个事务中,你第一次读取了a的值,此时其他线程改变了a的值,第二次读a的值,值就不一样了。所以一个事务内读取同一个值但是结果不同,故称为 不可重复读。 其重点在于 修改
幻读 :也是并发问题,比如当你执行 删除所有文档操作,同时,另一个事务增加了一个文档,所以当你执行完删除操作,发现还剩了一个,好像是幻觉一样。重点在于 增加和删除
-
线程数量的选择:
如果主要任务是计算,那么CPU处理能力是稀缺的,如果太多线程,反而导致大量的上下文切换开销,这种情况下,
线程数即为 CPU核数+1
如果是较多等待的任务。比如I/O ,
线程数可为: CPU核数 * 目标CPU利用率 *(1 +平均等待时间 / 平均工作时间)
相关文章
- 暂无相关文章
用户点评