JAVA技能点总结
基本
static:被修饰的成员变量和成员方法独立于该类的任何对象,被类的所有实例共享;被修饰的方法可以直接通过类名调用;static静态代码块在初始化类时被调用,先调用父类、再调用子类。
final:被修饰的属性和变量的值不能修改;类无法被继承;方法不能被重写。
transient:被修饰的属性无法被序列化。
foreach:对于数组,编译器采用的是添加goto指令,同for;对于实现了iterable的类,通过迭代器实现。
volatile:所有线程每次读取的都是变量的最新值;防止指令重排序;对变量进行写操作时,处理器会添加lock指令,作用:1、将处理器缓存回写到内存;2、导致其它处理器的缓存无效。
正则:^开始位置;$结束位置;集合
设计模式
项目中用到了哪些设计模式,如何使用
常用设计模式的优缺点
画出常用设计模式的UML图多线程
java.util.concurrent包:
1)Queue类型
LinkedBlockingQueue:基于链表,FIFO,容量默认为Integer.MAX_VALUE
ArrayBlockingQueue:基于对象数组,FIFO,需指定初始容量,可指定并通过ReentrantLock来实现公平性
PriorityBlockingQueue:按优先级的队列
DelayQueue:延迟期满才能返回元素
2)常用的线程池(使用Executors创建)
newSingleThreadExecutor :单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
newFixedThreadPool :定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newCachedThreadPool:可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newScheduledThreadPool :定长线程池,支持定时及周期性任务执行。
线程池使用方式:
1)execute:参数为实现runnable或callable接口的类
2)submit:参数为实现runnable或callable接口的类
3)Future:submit的返回值
4)Callable.call():可以有reutrn
5)Future.get():获取运行状态 或 返回值
线程池的实现原理:
1)如果运行的线程数量小于corePoolSize,则创建新线程;
2)如果运行的线程数量大于等于corePoolSize,则将任务加入阻塞队列;
3)如果任务无法加入阻塞队列,则创建新线程;
4)如果线程数量大于maxinumPoolSize,任务被拒绝,并调用RejectedExecutionHandler.rejectedExecution()
线程池的拒绝策略:
1)AbortPolicy(默认):直接抛出异常
2)CallerRunsPolicy:只用调用者所在线程来运行任务
3)DiscardOldestPolicy:丢弃最近的一个任务,并执行当前任务
4)DiscardPolicy:不处理,丢弃掉
线程池的关闭策略:
1)shutdown:将线程池状态设置为SHUTDOWN,循环调用空闲线程的interrupt方法
2)shutdownnow:将线程池状态设置为STOP,循环调用所有线程的interrupt方法
线程池的配置:cpu密集型,线程数量为Num CPU+1;io密集型,线程数量为2*Num CPU;通过Runtime.getRuntime().availableProcessors()获取cpu数量。synchronized和ReentrantLock(默认非公平锁)的区别:
1)任何对象都有一个moniter与之关联,代码块同步使用moniterenter和moniterexit指令实现;当一个moniter被持有后,将处于锁定状态;synchronized获取对象锁时是排它的,隐式支持重进入;
2)其它线程通过synchronized尝试获取对象锁时,将被阻塞;而ReentrantLock可以选择中断和尝试获取锁的时间;
3)ReentrantLock在调用lock后,必须在finally中进行unlock,即必须一一配对;
4)ReentrantLock有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放;synchronized的具体表现形式:
1)对于普通同步方法,锁是当前实例对象;
2)对于静态同步方法,锁是当前类的class对象
3)对于同步方法块,锁是括号里配置的对象;读写锁ReadWriteLock:允许多个线程在同一时间对某特定资源进行读取,但同一时间内只能有一个线程对其进行写入;实现类ReentrantReadWriteLock;使用读锁和写锁;
死锁的原理及排查方法
IO
同步:发出请求后,若关联方没有响应,该请求就不返回
异步:发出请求后就返回
阻塞:调用者在结果返回前,会一直等待,无法处理其它事情,一直等待响应
非阻塞:调用者无需一直等待响应
BIO(同步阻塞):调用者每发起一个请求,响应方就创建一个线程处理;调用者在请求响应前会一直等待。
NIO(同步非阻塞):调用者发起请求后,响应方将请求注册到多路复用器上,当有IO请求时才启线程处理;调用者发起请求后就返回,后续不间断地主动获取响应结果。
AIO(异步非阻塞):响应方处理完毕后,主动通知调用者。
java NIO的三大组成:
1)Channels and Buffers(通道和缓冲区):数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中
2)Asynchronous IO(异步IO):当线程从通道读取数据到缓冲区时,线程可以做其他事情
3)Selectors(选择器):用于监听多个通道的事件(比如:连接打开,数据到达),单个线程可以监听多个数据通道
java NIO与IO的区别:
1)IO是面向流,NIO是面向缓冲区。
2)IO的各种流是阻塞的,当一个线程调用read() 或 write()时,线程被阻塞,直到结束读取或写入;NIO是非阻塞的,仅从缓冲区中读取数据,如果没有可用数据,则线程可以处理其它channel。
NIO:
1)buffer:存放数据的缓冲区,分为CharBuffer和ByteBuffer,底层都是数组;ByteBuffer.allocate()或CharBuffer.allocate()获取buffer;capacity容量,limit可以读写的最后位置,position可以读写的开始位置;flip()重置position,将limit设置为原position的位置,为读做准备;clear()重置下标,不清除数据;compact()将未读数据挪至起始位置,可以读剩余未读数据;hasRemaining()是否还有可读数据;
2)channel:数据流的通道;可以从io流中通过getChannel()获取;read(Buffer)将数据流读入缓冲区;
3)selector:能够检测channelJDK源码
String.hashCode():((1ascii)*31+2ascii)*31+3ascii…
ReentrantLock的源代码,参见:(http://www.cnblogs.com/xrq730/p/4979021.html)
1)非公平锁和公平锁:公平锁,按加锁顺序来获取锁,先请求先获取锁,线程上下文切换多,可能导致效率低下;非公平锁,抢占式获取锁,性能较高;默认非公平锁。
2)lock()
2.1)通过cas尝试修改state,如果成功,则获取锁;若失败,则再次尝试获取锁
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
2.2)再次尝试获取锁
如果尝试失败且添加至阻塞队列失败,则中断自己。
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
2.3)尝试获取锁
如果成功,则获取锁,且修改state,同一线程多次获取锁,则state一直增加,直到调用unlock()
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
AtomicInteger:可实现原子操作;compareAndSet首先判断当前值是否等于current,如果相等,表明AtomicInteger没有被其它线程修改,则直接修改;如果不等,继续循环并尝试修改。
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
private static final Unsafe unsafe = Unsafe.getUnsafe();
Object类中的方法以及每个方法的作用
7. 框架
项目中使用的框架
MyBatis中\$和#的区别:#将参数解析为字符串,\$ 将参数原样输出;#可以防止SQL注入;$一般传入数据库对象,如表名
JDK动态代理和CG LIB的区别:
代理:当一个对象不直接引用另一个对象(目标对象),可以应用代理模式在这两者之间构建一个桥梁--代理对象。
1、JDK动态代理:只能针对实现了接口的类
2、CG LIB:针对实现类进行代理,生成目标类的子类,并重写其中的方法
8. 数据库
union和union all的区别、left join、几种索引及其区别
9. 数据结构和算法分析
数组、链表、平衡树、AVL树、红黑树
10. Java虚拟机
Java虚拟机的内存布局:
1)程序计数器:线程私有,字节码解释器通过改变其值来获取下一条指令。
2)虚拟机栈(局部变量表):线程私有,存放基本类型、对象引用。
3)本地方法栈:线程私有,为虚拟机所使用到的native方法服务。
4)堆(GC堆)):线程共享,存放对象实例和数组。
5)方法区:线程共享,存放类信息、常量、静态变量等。
5.1)运行时常量池:存放字面量和符号引用,具备动态性,常用的是String.intern()。
判断对象是否存活的方式
1、引用计数法:给对象添加引用计数器,每有一个引用就+1,引用失效则-1,若引用为0,则表明对象不可用;很难解决对象间循环引用的问题。
2、可达性分析法:以GC Roots对象为起点,向下搜索,走过的路径是“引用链”,当一个对象到GC Roots没有任何引用链,则表明对象不可用。
可作为GC Roots的对象:
1)虚拟机栈中引用的对象
2)方法区中静态属性引用的对象
3)方法区中常量引用的对象
4)本地方法栈中JNI(native方法)引用的对象
GC算法:
1)标记-清除:效率低;内存碎片多。
2)复制算法:将存活对象复制到另一半内存空间,简单高效,但压缩了内存空间。
3)标记-整理:标记后,将存活对象向一端移动,再清理。
几种垃圾收集器
1)串行
2)并行
类加载机制,也就是双亲委派模型
Java内存模型
happens-before规则:即先行发生规则;如果操作A先行发生于操作B,在发生操作B之前,操作A产生的影响都能被操作B观察到;详见:http://blog.csdn.net/ns_code/article/details/17348313
volatile关键字使用规则
11. Web
分布式Session的几种实现方式:
1)Session Replication(session复制):将一台机器的session数据广播复制到其它机器。
2)Session Sticky(粘性session):固定用户请求到某一台机器。
3)缓存集中式管理:将session存入分布式缓存集群中的机器,用户访问时先从缓存中获取session。
Session和Cookie的区别和联系以及Session的实现原理
一致性Hash算法
web.xml:Filter、Servlet、Listener
get/post的区别
1)get:获取数据,将参数附在url后面(中文使用base64编码),可传输数据量较少
2)post:提交/修改数据,将参数附在http请求体里,可传输数据量多
请求转发(forward)/重定向(redirect)的区别:forward是服务器获取目标地址的数据,并返回给客户端,客户端不知道数据来源发生了变化;redirect是服务器让客户端重新发送请求去获取数据。
HTTPS的实现原理
SOA和RPC
12.大型网站架构
1)前端:浏览器优化(合并http请求,页面压缩,页面缓存),CDN,动静分离、静态资源独立部署(将http请求分离),反向代理(页面缓存),DNS(负载均衡)
2)应用层:集群(负载均衡),session管理(session复制、session粘性、集中式缓存),动态页面静态化,业务拆分(解耦)
3)服务层:分布式消息,分布式服务(微服务),分布式缓存和配置
4)存储层:分布式数据库,数据同步,主从(读写分离)
13.java调优
http://blog.csdn.net/zhengchao1991/article/details/53188629