-
-
Save steven-zou/7ce14e01d2ad7cd07091 to your computer and use it in GitHub Desktop.
| 引用计数法(Reference Counting): | |
| 1. 有引用,计数器+1, 引用失效,则计数器-1 | |
| 2. 实现简单,判定效率高 | |
| 3. 未在主流虚拟机中使用,因为解决不了循环引用的问题 | |
| 可达性分析(Reachability Analysis): | |
| 1. 以GC root对象作为起点,向下搜索 | |
| 2. 所走过的路径为引用链, | |
| 3. 当一个对象到GC root 没有任何的引用链的时候,则不可达,可以回收 | |
| 4. 可作为GC root的对象 | |
| 4.1 虚拟机栈中引用对象 | |
| 4.2 方法区中的静态属性引用的对象 | |
| 4.3 方法区中的常量引用对象 | |
| 4.4 本地方法栈中的JNI引用对象 | |
| 垃圾收集算法: | |
| 1. 标记-清除 (Mark-Sweep) | |
| 问题:效率不高,会产生大量不连续的内存碎片 | |
| 2. 复制算法 | |
| 等大的内存块,讲存活的对象复制到另外一块,再把已使用过的内存空间一次清理掉 | |
| 现代商业虚拟机都依靠此技术来回收新生代 | |
| 问题:如果对象存活率较高时,进行太多的复制,效率变低 | |
| 3. 标记-整理算法 | |
| 先标记,之后所有存活对象向一边移动,然后直接清理掉端边界以外的内存 | |
| 现代商业虚拟机都采用的是分代收集算法 | |
| Java Thread <-> Work memory | | | |
| | | | |
| Java Thread <-> Work memory <-> | Save &Load | Major Memory | |
| | | | |
| Java Thread <-> Work memory | | | |
| Memory operations: | |
| lock -> major memory | |
| unlock-> major memory | |
| read -> major | |
| load -> work memory | |
| use -> work | |
| assign -> work | |
| store ->work | |
| write -> major |
| http://www.360doc.com/content/12/0113/08/1073512_179088229.shtml |
| 用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。 | |
| Read Uncommitted(读取未提交内容) | |
| 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未 | |
| 提交的数据,也被称之为脏读(Dirty Read)。 | |
| Read Committed(读取提交内容) | |
| 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔 | |
| 离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能 | |
| 返回不同结果。 | |
| Repeatable Read(可重读) | |
| 这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题: | |
| 幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时 | |
| ,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。 | |
| Serializable(可串行化) | |
| 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个 | |
| 级别,可能导致大量的超时现象和锁竞争。 | |
| References: http://xm-king.iteye.com/blog/770721 |
| OAuth 2.0 的基本流程 | |
| OAuth 2.0 相对于1.0的主要改进 |
| TCP连接是面向连接的,所谓的面向连接就是,当计算机双向通信时必需先建立连接,然后才能进行数据的传输,最后还要拆除连接。而同在一个 | |
| 网络层的UDP传输,是面向非连接的传输,也不是可靠的。 | |
| 位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急) | |
| Client <------------> Server | |
| ->SYN=j | |
| SYN=J+1&ACK=K<- | |
| ->ACK=K+1 | |
| 实例: | |
| IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836 | |
| IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837 | |
| IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1 | |
| 第一次握手:192.168.1.116发送位码syn=1,随机产生seq number=3626544836的数据包到192.168.1.123,192.168.1.123由SYN=1知道 | |
| 192.168.1.116要求建立联机; | |
| 第二次握手:192.168.1.123收到请求后要确认联机信息,向192.168.1.116发送ack number=3626544837,syn=1,ack=1,随机产生seq=1739326486 | |
| 的包; | |
| 第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确, | |
| 192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功。 | |
| 由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来 | |
| 终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭 | |
| 的一方将执行主动关闭,而另一方执行被动关闭。 | |
| Client <------------> Server | |
| -->FIN | |
| ACK<-- | |
| CLOSE< | |
| FIN<-- | |
| -->ACK | |
| >CLOSE | |
| ======================= | |
| CLOSED: 这个没什么好说的了,表示初始状态。 | |
| LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。 | |
| SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态, | |
| 很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。 | |
| 因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。 | |
| SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态, | |
| 并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。 | |
| ESTABLISHED:这个容易理解了,表示连接已经建立了。 | |
| FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是: | |
| FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。 | |
| 而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以 | |
| FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。 | |
| FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方, | |
| 我暂时还有点数据需要传送给你,稍后再关闭连接。 | |
| TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时 | |
| 带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。 | |
| CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先 | |
| 收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收 | |
| 到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么 | |
| 就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。 | |
| CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个 | |
| ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么 | |
| 你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。 | |
| LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到 | |
| CLOSED可用状态了。 | |
| ====================== | |
| 1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢? | |
| 这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。 | |
| 但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上 | |
| 会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文 | |
| 多数情况下都是分开发送的. | |
| 2.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态? | |
| 这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样); | |
| 但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未 | |
| 收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。 |
| Weak references | |
| A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references | |
| allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. | |
| You create a weak reference like this: | |
| ===================================================== | |
| WeakReference weakWidget = new WeakReference(widget); | |
| ===================================================== | |
| and then elsewhere in the code you can use weakWidget.get() to get the actual Widget object. Of course the weak reference | |
| isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) | |
| that weakWidget.get() suddenly starts returning null. | |
| Soft references | |
| A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. | |
| An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next | |
| garbage collection cycle, but an object which is softly reachable will generally stick around for a while. | |
| SoftReferences aren't required to behave any differently than WeakReferences, but in practice softly reachable objects are | |
| generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache, such as the | |
| image cache described above, since you can let the garbage collector worry about both how reachable the objects are | |
| (a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming. | |
| Soft Reference 虽然和 Weak Reference 很类似,但是用途却不同。 被 Soft Reference 指到的对象,即使没有任何 Direct Reference, | |
| 也不会被清除。一直要到 JVM 内存不足时且 没有 Direct Reference 时才会清除,SoftReference 是用来设计 object-cache 之用的。 | |
| 如此一来 SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误 (OutOfMemoryError)。我觉得 Soft Reference | |
| 也适合拿来实作 pooling 的技巧。 | |
| Comments: | |
| ----------- | |
| The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a | |
| SoftReference if there isn't pressure on the available memory. One detail: the policy for the | |
| "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by | |
| preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance | |
| high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all. | |
| Strong referebce(强引用): 默认的引用形式,只要引用存在,则永远不会被回收 | |
| Phantom Reference: 虚引用,完全不会对其生存时间构成影响,唯一的目的就是能在这个对象被收集器回收时收到一个系统通知 |
PRODUCER-CONSUMER Problem part2:
private LinkedBlockingQueue list = new LinkedBlockingQueue(MAX_COUNT);
put()方法:类似于我们上面的生产者线程,容量达到最大时,自动阻塞。
take()方法:类似于我们上面的消费者线程,容量为0时,自动阻塞。
排序算法分析:
Sort Methods | Average Time | Worst Time | Space
简单排序 O(n^2) O(n^2) O(1)
快速排序 O(nlogN) O(n^2) O(logN)
堆排序 O(nlogN) O(nlogN) O(1)
归并排序 O(nlogN) O(nlogN) O(n)
基数排序 O(d(n+rd)) O(d(n+rd)) O(rd)
几个排序算法:
public void StraightInsertionSort(int[] arr){
for(int i=1;i<arr.length;i++){
if(arr[i-1]>arr[i]){
int temp = arr[i];
int j=i-1;
for(;j>=0&&temp<arr[j];j--){
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
}
public void shellSort(int[] arr){
double dk = arr.length;
int temp = 0;
while(true){
dk = Math.ceil(dk/2);
int d = (int)dk;
for(int x=0;x<d;x++){
for(int i=x+d;i<arr.length;i+=d){
if(arr[i-d]>arr[i]){
temp = arr[i];
int j=i-d;
for(;j>=0&&temp<arr[j];j-=d){
arr[j+d] =arr[j];
}
arr[j+d] = temp;
}
}
}
if(d==1){
break;
}
}
}
public void selectionSort(int[] arr){
for(int i=0,len=arr.length;i<len;i++){
int temp=arr[i], position=i;
for(int j=i+1;j<len;j++){
if(arr[j]<temp){
temp=arr[j];
position=j;
}
}
arr[position] =arr[i];
arr[i] = temp;
}
}
public void quickSort(int[] arr){
if(arr!=null&&arr.length>0){
quickSort(arr,0,arr.length-1);
}
}
private void quickSort(int[] arr, int low, int high){
if(low<high){
int pv = partition(arr,low,high);
quickSort(arr,low,pv-1);
quickSort(arr,pv+1,high);
}
}
private int partition(int[] arr, int low, int high){
int pv = arr[low];
while(low<high){
while(low<high&&arr[high]>=pv){
high--;
}
arr[low]=arr[high];
while(low<high&&arr[low]<=pv){
low++;
}
arr[high]=arr[low];
}
arr[low]=pv;
return low;
}
ORM:
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射.
Drawbacks:
- 自动化意味着映射和关联管理,代价是牺牲性能
- 面向对象的查询语言(X-QL)不能完全的屏蔽掉数据库层的设计,增加学习成本
- 对于复杂查询,ORM仍然力不从心
OOP 四大特征 "抽象"、"封装"、"继承"、"多态"
OOP 四大原则:
- SRP 单一职责原则: 一个类,应该仅有一个引起它变化的原因
- 开放封闭原则: 软件实体(类、模块、函数等)应该可以扩展,但不可修改
- 依赖倒转原则: 抽象不应该依赖细节,细节应该依赖抽象(面向接口编程)
- 里氏代换原则: 子类型必须能够替换掉他们的父类型
AOP技术的具体实现,无非也就是通过动态代理技术或者是在程序编译期间进行静态的"织入"方式。下面是这方面技术的几个基本术语: 1、join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。 2、point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。 3、advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。 4、aspect(方面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。 5、introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的 OP工具又将其称为mixin。
JDK动态代理:
包含一个类和一个接口:
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。
Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
Ps:类加载器
在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器;
Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的;
Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类;
AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。
PRODUCER-CONSUMER Problem:
public interface IStorage {
void produce();
void consume();
}
import java.util.ArrayList;
import java.util.List;
public class Storage implements IStorage{
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CStorage implements IStorage {
}
public class Producer implements Runnable {
}
public class Consumer implements Runnable {
}
public class Main {
}