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.