Java一些小知识整理,用于面试
1.CloseGuard
CloseGuard源码
大多数出现该情况是内存泄漏,你占用了资源没有释放或者关闭,比如数据库。
CloseGuard is a mechanism for flagging implicit finalizer cleanup of
* resources that should have been cleaned up by explicit close
* methods (aka "explicit termination methods" in Effective Java).
* A simple example: <pre> {@code
* class Foo {
*
* private final CloseGuard guard = CloseGuard.get();
*
* ...
*
* public Foo() {
* ...;
* guard.open("cleanup");
* }
*
* public void cleanup() {
* guard.close();
* ...;
* }
*
* protected void finalize() throws Throwable {
* try {
* if (guard != null) {
* guard.warnIfOpen();
* }
* cleanup();
* } finally {
* super.finalize();
* }
* }
* }
* }
源码的列子很清楚,需要finalize配合使用,它能制定在你的Foo,回收必须强制调用cleanup回收,不然在对象析构的时候就报错。具体错误官方有。
出自深入理解Android(卷2).邓平凡.2012-363页2.序列化
出自Effective Java 中文第二版
3.泛型
出自Effective Java 中文第二版4.同步,重入锁,volatile
什么叫锁,计算机实现原理:
一般分为2类:
1.缓存加锁:就是如果缓存在处理器缓存行中内存区域在LOCK操作期间被锁定,当它执行锁操作回写内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改被两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时会起缓存行无效,在例1中,当CPU1修改缓存行中的i时使用缓存锁定,那么CPU2就不能同时缓存了i的缓存行。
2.总线加锁:总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占使用共享内存
并发原理
ConcurrentHashMap
出自Java并发编程实战(中文版)5.2.1章
ConcurrentMap
Paste_Image.pngCopyOnWriteArrayList
出自Java并发编程实战(中文版)5.2.2章BlockingQueue
出自Java并发编程实战(中文版)5.3章BlockingDeque
出自Java并发编程实战(中文版)5.3.3章同步工具类
出自Java并发编程实战(中文版)5.5章闭锁
闭锁是一次性对象的使用,一旦进入终止状态,就不能被重置。
出自Java并发编程实战(中文版)5.5.1章
解释下原理:
按前面红框中游戏玩家举例。我有5个玩家,进入我的主机,每个玩家是一个线程。
我作为主机控制着,我希望知道所有玩家作为准备后,需要多长时间,然后进行同步下一步任务。
这时候startGate会锁住Thread中的Task,等你进来之后就开始countDown让你准备。
最后endGate,正如文中所说,主机不会去关系某个人做完准备工作的时间,当5个人全部做完,那么我主机就知道所有人总时间了。
另一个闭锁的使用例子
信号量
重入定义,出自Java并发编程实战(中文版)5.5.4章
栅栏
重入定义,出自Java并发编程实战(中文版)5.5章
重入
重入定义,出自Java并发编程实战(中文版)2.3.2章long和double的坑:
同步锁的优化,分解锁和分段锁
分解锁优化
分段锁
Condition
出自Java并发编程实战(中文版)14.3章
这里解释下lock.lock()用于同步使用了,也就相当于一个synchronizer,真正阻塞在await()。
出自Java并发编程实战(中文版)4章
volatile原则就是:仅当一个变量参与到包含其他状态变量的不变性条件时,才可以声明volatile类型。也就是说这货是个独立的,不能带节奏以后,其他变量值会被他影响。
并发的效率
下面看一个“错误”加锁例子:
出自Java并发编程实战(中文版)4章4.异步
Future
出自Java并发编程实战(中文版)5.5.2章
Callable和Future
出自Java并发编程实战(中文版)6.3.2章
ExecuteCompletionService
出自Java并发编程实战(中文版)6.3.3章
这里解释下for循环中的take(),是从ExecuteCompletionService中BlockingQueue中拿出来的Future,本身不会阻塞。但Future拿结果get会阻塞,直到数据完成。
5.对象回收
C++是用引用计数器,Java是用GC Root
6.守护线程
出自Java并发编程实战(中文版)7.4.2章7.线程池使用
一个自定义线程池执行器,注意策略使用
设置线程错误堆栈
一个信号量使用(Semaphore),先条件大小阻塞,才有任务提交
注意学习上面Semaphore使用,一般可以配合ThreadLoacl使用。
出自Java并发编程实战(中文版)8.9章
注意学习上面ThreadLoacl使用,每个线程有自己实例空间堆栈,不受其他线程影响,不能在线程通信使用。
8.显示锁
出自Java并发编程实战(中文版)13.1章就性能方面还是sychronized效率高,但伸缩性和扩展性没有显示锁好用
9.显示锁读写锁
10非阻塞算法
栈
说明下:compareAndSet既能提供原子性,又能提供可见性。当一个线程需要修改栈状态时,它能有写入volaite类型一样,快速同步内存效果。