HTTP/2
HTTP/1连接
在HTTP1中,每个请求和响应都占用一个TCP链接,尽管有Keep-Alive机制可以复用,但是在每个连接上同时只能有一个请求/响应,这意味着完成响应之前,这个连接不能用于其他请求。如果浏览器需要向同一个域名发送多个请求,需要在本地维护一个FIFO队列,完成一个再发送下一个。这样,从服务端完成请求开始回传,到收到下一个请求之间的这段时间,服务器处于空闲状态。
后来,人们提出了HTTP管道的概念,试图把本地的FIFO队列挪到服务端。它的原理是这样的:浏览器一股脑把请求都发送给服务端,然后等着就可以了。这样服务端就可以在处理完一个请求后,马上处理下一个,不会有空闲了。甚至服务端还可以多线程并行处理多个请求。
HTTP/1优化
开源
既然一个TCP连接同时只能处理一个HTTP消息,那多开几条TCP连接不就解决这个问题了。
浏览器确实是这样做的。现代浏览器一般允许同域名并发6~8个连接。这个数字为什么不能更大呢?实际上这是出于公平性的考虑,每个连接对于服务器来说都会带来一定开销,如果浏览器不加以限制,一个性能好、带宽足的终端就可能耗尽服务器所有资源,造成其他人无法使用。
我们还会使用Cookie-Free Domain来减少静态文件带cookies的问题
节流
合并图片、js、css等
HTTP/2
开启Server Push。HTTP/2的多路复用特征,使得可以在一个连接上同时打开多个流,双向传输数据。Server Push,意味着服务端可以在发送页面HTML时主动推送其他资源,而不用等到浏览器解析到相应位置,发起请求再响应。另外,服务端主动推送的资源不是被内联在页面里,它们有自己独立的URL,可以被浏览器缓存。
Reference
https://imququ.com/post/http2-and-wpo-1.html
https://imququ.com/post/http2-and-wpo-2.html
HTTP2-high-perf-browser-networking.pdf
Java中的Object对象
Java把现实中的任何事物都当做一个对象(Object),Java是面向对象的,就是Object-Oriented简称OO
Object在Java中被定义为一个顶级父类,它是任何类的父类,我们可以显示的继承它,也可以隐式继承
Object类中定义的常用方法
equals(Object obj)
equals()方法与==的区别:

==比较的是两个引用的值,即两个对象的地址。两次创建的对象是相互对立的,都各自分配了独立的内存空间,所有str1 != str2
equals()比较的是两个引用指向的对象的实际的值,涉及到对象的属性和方法。上例中两个对象的值都为Hello,所以str1.equals(str2)

由于Java中String类型是不可变的,也就是说在创建了一个字符串之后,如果想修改这个字符串的值是不能直接在原来的内存中修改存储的,而是需要重新分配一个内存空间用来存放新的内存空间。
String类的这种特性造成在对String对象进行创建或操作时非常浪费内存空间,为了解决这个问题,Java中引出一个字符串池的概念(a pool of String)。即:如果当前准备新创建的字符串对象的值在复用池中已经存在,那么就不在生成新的对象,而是复用池中已有的字符串对象,新建的字符串和原来同值的字符串内存地址是相同的。
注意的是,这种字符串池的机制只有采用Object obj ="Hello"方式(而非用new关键字)声明String对象的时候才有效。
hashCode()
Object类中定义了hashCode()方法决定了所有的对象都可以调用其hashCode()方法。
在HashMap的存储实现中,系统会根据对象的hashCode()值来决定每个元素的存储位置。
这个时候会有一个疑问,就是会不会出现两个对象的hashCode()值相同呢?
- 对象相等则hashCode()一定相等;
- hashCode()相等对象未必相等。
hashCode()存储机制中,不同的hashCode()值的对象会被分配到不同的“桶”里面,hashCode()值相同的对象会被放进同一个“桶”里面。在查询的过程中,一般是先遍历所有的桶再遍历桶里面的元素,所以为了能有一个高效的查询效果,我们应该尽可能的让所有的对象都被分配的自己独有的“桶”里面,这样才能最快的实现查询,要实现这样的要求就需要这些对象的hashCode()值不相同。
hashCode()、equals()和==三者的关系
- 如果是基本变量,没有
hashCode()和equals()方法,基本变量的比较方式就只有==。因为他们不是对象,当然是可以通过Java中的包装类将他们转换成对象后还是可以调用hashCode()和equals()()方法。 - 如果是变量,由于在Java中所有变量定义都是一个指向实际存储的一个句柄(你可以理解为c++中的指针),
==是比较句柄的地址(你可以理解为指针的存储地址),而不是句柄指向的实际内存中的内容,- 如果要比较实际内存中的内容,那就要用
equals()方法, - 但是如果是我们自己定义的一个类,比较自定义类用
equals()和==是一样的,都是比较句柄地址,因为自定义的类是继承于Object,而Object中的equals()就是用==来实现的,所以在自定义类的情况下重写equals()方法会是一个良好的习惯,否则失去了equals()方法存在的意义了。 - 那为什么我们用的String等等类型
equals()是比较实际内容呢,是因为String等常用类已经重写了Object中的equals()方法,让equals()来比较实际内容。
hashCode()在一般的应用中我们不需要了解hashCode()的用法,但当我们用到HashMap,hashset等集合类时要注意下hashCode()。我们想通过一个Object的key来拿HashMap的value,HashMap的工作方法是,通过你传入的Object的hashCode()在内存中找地址,当找到这个地址后再通过equals()()方法来比较这个地址中的内容是否和你原来放进去的一样,一样就取出value。- 所以这里要匹配2部分,
hashCode()和equals()。但假如说我们new一个Object作为key去拿value是永远得不到结果的,因为每次new一个Object,这个Object的hashCode()是永远不同的,所以我们要重写hashCode(),你可以令你的hashCode()是Object中的一个恒量,这样永远可以通过你的Object的hashCode()来找到key的地址,然后你要重写你的equals()方法,使内存中的内容也相等
首先,从语法角度,也就是从强制性的角度来说,hashCode()和equals()是两个独立的,互不隶属,互不依赖的方法,equals()成立与hashCode()相等这两个命题之间,谁也不是谁的充分条件或者必要条件。
但是,从为了让我们的程序正常运行的角度,我们一定要(正确)重载hashCode(),使得equals()成立的时候,hashCode()相等,也就是
a.equals(b) -> a.hashCode()== b.hashCode()
总结一下,equals()是对象相等性比较,hashCode()是计算对象的散列值,当然他们的依据是对象的属性。
对于equals(),一般我们认为两个对象同类型并且所有属性相等的时候才是相等的,在类中必须改写equals(),因为Object类中的equals()只是判断两个引用变量是否引用同一对象,如果不是引用同一对象,即使两个对象的内容完全相同,也会返回false。当然,在类中改写这个equals()时,你也可以只对部分属性进行比较,只要这些属性相同就认为对象是相等的。
对于hashCode(),只要是用在和哈希运算有关的地方,和equals()一样,在你的类中也应该改写。当然如果两个对象是完全相同的,那么他们的`hashCode()当然也是一样的,但是象前面所述,规则可以由你自己来定义,因此两者之间并没有什么必然的联系。
当然,大多数情况下我们还是根据所有的属性来计算hashCode()和进行相等性比较。
Reference
http://blog.chinaunix.net/uid-26981819-id-4462638.html
http://www.cnblogs.com/I-am-Betty/archive/2010/09/06/1819375.html
Copyright © 2016 Powered by MWeb, Theme used GitHub CSS.












