版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Java基礎(chǔ)知識(shí)面試題(2022優(yōu)化版)
Java概述
談?wù)勀銓?duì)Java平臺(tái)的理解?“Java是解釋執(zhí)行〞,這句話正確嗎?
對(duì)Java平臺(tái)的理解主要包括下列三個(gè)方面:面向?qū)ο蠛秃诵念悗?kù)方面,跨平臺(tái)方面和虛擬機(jī)和垃圾收集
面向?qū)ο蠛秃诵念悗?kù)方面
Java是一門面向?qū)ο缶幊陶Z(yǔ)言,極好地實(shí)現(xiàn)了面向?qū)ο罄碚?,允許程序員以優(yōu)雅的思維方式進(jìn)行復(fù)雜的編程。
Java核心類庫(kù)提供了包含匯合容器、線程相關(guān)類、IO/NIO、J.U.C并發(fā)包,異常和平安等類庫(kù),極大地方便了程序員的開(kāi)發(fā);
JDK提供的工具包含:根本的編譯工具、虛擬機(jī)性能檢測(cè)相關(guān)工具等。
跨平臺(tái)方面
所謂的“一次編寫,到處運(yùn)行〞〔Writeonce,runanywhere〕,能夠非常容易地獲得跨平臺(tái)能力。跟c/c++最大的不同點(diǎn)在于,c/c++編程是面向操作系統(tǒng)的,需要開(kāi)發(fā)者極大地關(guān)懷不同操作系統(tǒng)之間的差別性;而Java平臺(tái)通過(guò)虛擬機(jī)屏蔽了操作系統(tǒng)的底層細(xì)節(jié),使得開(kāi)發(fā)者無(wú)需過(guò)多地關(guān)懷不同操作系統(tǒng)之間的差別性。
通過(guò)增加一個(gè)間接的中間層來(lái)進(jìn)行〞解耦“是計(jì)算機(jī)領(lǐng)域非常常用的一種〞藝術(shù)手法“,虛擬機(jī)是這樣,操作系統(tǒng)是這樣;
虛擬機(jī)和垃圾收集
另外就是Java虛擬機(jī)和垃圾收集〔GC,GarbageCollection〕,Java通過(guò)垃圾收集器〔GarbageCollector〕回收分配內(nèi)存,大局部情況下,程序員不需要自己操心內(nèi)存的分配和回收。
同時(shí),圍繞虛擬機(jī)的效率問(wèn)題展開(kāi),將波及到一些優(yōu)化技術(shù),示例:JIT、AOT。因?yàn)槿绻摂M機(jī)加載字節(jié)碼后,一行一行地解釋執(zhí)行,這勢(shì)必會(huì)影響執(zhí)行效率。所以,對(duì)于這個(gè)運(yùn)行環(huán)節(jié),虛擬時(shí)機(jī)進(jìn)行一些優(yōu)化處理,示例JIT技術(shù),會(huì)將熱點(diǎn)代碼編譯成機(jī)器碼。而AOT技術(shù),是在運(yùn)行前,通過(guò)工具直接將字節(jié)碼轉(zhuǎn)換為機(jī)器碼。
對(duì)于“Java是解釋執(zhí)行〞這句話,這個(gè)說(shuō)法不太準(zhǔn)確。我們開(kāi)發(fā)的Java的源代碼,首先通過(guò)Javac編譯成為字節(jié)碼〔bytecode〕,然后,在運(yùn)行時(shí),通過(guò)Java虛擬機(jī)〔JVM〕內(nèi)嵌的解釋器將字節(jié)碼轉(zhuǎn)換成為最終的機(jī)器碼。但是常見(jiàn)的JVM,比方我們大多數(shù)情況使用的OracleJDK提供的HotspotJVM,都提供了JIT〔Just-In-Time〕編譯器,也就是通常所說(shuō)的動(dòng)態(tài)編譯器,JIT能夠在運(yùn)行時(shí)將熱點(diǎn)代碼編譯成機(jī)器碼,這種情況下局部熱點(diǎn)代碼就屬于編譯執(zhí)行,而不是解釋執(zhí)行了。
JVM、JRE和JDK的關(guān)系
JVM
JavaVirtualMachine是Java虛擬機(jī),Java程序需要運(yùn)行在虛擬機(jī)上,不同的平臺(tái)有自己的虛擬機(jī),因此Java語(yǔ)言可以實(shí)現(xiàn)跨平臺(tái)。
JRE
JavaRuntimeEnvironment包括Java虛擬機(jī)和Java程序所需的核心類庫(kù)等。核心類庫(kù)主要是java.lang包:包含了運(yùn)行Java程序必不可少的系統(tǒng)類,如包裝類型、根本數(shù)學(xué)函數(shù)、字符串處理、線程、異常處理類等,系統(tǒng)缺省加載這個(gè)包。如果想要運(yùn)行一個(gè)開(kāi)發(fā)好的Java程序,計(jì)算機(jī)中只需要安裝JRE即可。
JDK
JavaDevelopmentKit是提供應(yīng)Java開(kāi)發(fā)人員使用的,其中包含了Java的開(kāi)發(fā)工具,也包括了JRE。所以安裝了JDK,就無(wú)需再獨(dú)自安裝JRE了。其中的開(kāi)發(fā)工具:編譯工具(javac.exe),打包工具(jar.exe)等
JVM&JRE&JDK關(guān)系圖
什么是跨平臺(tái)性?原理是什么
所謂跨平臺(tái)性,是指java語(yǔ)言編寫的程序,一次編譯后,可以在多個(gè)系統(tǒng)平臺(tái)上運(yùn)行。
實(shí)現(xiàn)原理:Java程序是通過(guò)虛擬機(jī)在系統(tǒng)平臺(tái)上運(yùn)行的,只要該系統(tǒng)安裝相應(yīng)的java虛擬機(jī),該系統(tǒng)就可以運(yùn)行java程序。
什么是字節(jié)碼?采用字節(jié)碼的最大好處是什么
字節(jié)碼:Java源代碼經(jīng)過(guò)虛擬機(jī)編譯器編譯后產(chǎn)生的文件〔即擴(kuò)展為.class的文件〕,它不面向任何特定的處理器或操作系統(tǒng),只面向虛擬機(jī)。
采用字節(jié)碼的好處:
Java語(yǔ)言通過(guò)字節(jié)碼的方式,在一定程度上解決了傳統(tǒng)解釋型語(yǔ)言執(zhí)行效率低的問(wèn)題,同時(shí)又保存了解釋型語(yǔ)言可移植的特點(diǎn)。所以Java程序運(yùn)行時(shí)比擬高效,而且,由于字節(jié)碼并不面向任何特定的處理器或操作系統(tǒng),因此,Java程序無(wú)須重新編譯便可在多種不同的計(jì)算機(jī)上運(yùn)行。
先看下java中的編譯器和解釋器:
Java源程序經(jīng)過(guò)編譯器編譯后變成字節(jié)碼,字節(jié)碼由虛擬機(jī)解釋執(zhí)行,虛擬機(jī)將每一條要執(zhí)行的字節(jié)碼送給解釋器,解釋器將其翻譯成特定機(jī)器上的機(jī)器碼,然后在特定的機(jī)器上運(yùn)行
Java源代碼---->編譯器---->jvm可執(zhí)行的Java字節(jié)碼(即虛擬指令)---->jvm---->jvm中解釋器----->機(jī)器可執(zhí)行的二進(jìn)制機(jī)器碼---->程序運(yùn)行。
根底語(yǔ)法
Java有哪些數(shù)據(jù)類型
定義:Java語(yǔ)言是強(qiáng)類型語(yǔ)言,對(duì)于每一種數(shù)據(jù)都定義了明確的具體的數(shù)據(jù)類型,在內(nèi)存中分配了不同大小的內(nèi)存空間。
分類
根本數(shù)據(jù)類型
整數(shù)類型(byte,short,int,long)
浮點(diǎn)類型(float,double)
數(shù)值型
字符型(char)
布爾型(boolean)
引用數(shù)據(jù)類型
類(class)
接口(interface)
數(shù)組([])
Java根本數(shù)據(jù)類型圖
訪問(wèn)修飾符public,private,protected,以及不寫〔默認(rèn)〕時(shí)的區(qū)別
定義:Java中可以使用訪問(wèn)修飾符來(lái)愛(ài)護(hù)對(duì)類、變量、辦法的訪問(wèn)。Java支持4種不同的訪問(wèn)權(quán)限。
分類
private:在同一類內(nèi)可見(jiàn)。使用對(duì)象:變量、辦法。注意:不能修飾類〔外部類〕
default(即缺省,什么也不寫,不使用任何關(guān)鍵字〕:在同一包內(nèi)可見(jiàn),不使用任何修飾符。使用對(duì)象:類、接口、變量、辦法。
protected:對(duì)同一包內(nèi)的類和所有子類可見(jiàn)。使用對(duì)象:變量、辦法。注意:不能修飾類〔外部類〕。
public:對(duì)所有類可見(jiàn)。使用對(duì)象:類、接口、變量、辦法
訪問(wèn)修飾符圖
&和&&的區(qū)別
&運(yùn)算符有兩種用法:(1)按位與;(2)邏輯與。
&&運(yùn)算符是短路與運(yùn)算。邏輯與跟短路與的差異是非常巨大的,雖然二者都要求運(yùn)算符左右兩端的布爾值都是true整個(gè)敘述式的值才是true。&&之所以稱為短路運(yùn)算,是因?yàn)槿绻?&左邊的敘述式的值是false,右邊的敘述式會(huì)被直接短路掉,不會(huì)進(jìn)行運(yùn)算。
注意:邏輯或運(yùn)算符〔|〕和短路或運(yùn)算符〔||〕的差異也是如此。
@$finalfinallyfinalize區(qū)別
final是一個(gè)修飾符關(guān)鍵字,可以修飾類、辦法、變量,修飾類表示該類不能被繼承、修飾辦法表示該辦法不能被重寫、修飾變量表示該變量是一個(gè)常量不能被重新賦值。
finally是一個(gè)異常處理的關(guān)鍵字,一般作用在try-catch-finally代碼塊中,在處理異常的時(shí)候,通常我們將一定要執(zhí)行的代碼放在finally代碼塊中,表示不論是否出現(xiàn)異常,該代碼塊都會(huì)執(zhí)行,一般用來(lái)寄存一些關(guān)閉資源的代碼。
finalize是屬于Object類的一個(gè)辦法,該辦法一般由垃圾回收器來(lái)調(diào)用,它的設(shè)計(jì)目的是保證對(duì)象在被垃圾收集前完成特定資源的回收。finalize機(jī)制現(xiàn)在已經(jīng)不推薦使用,并且在JDK9被標(biāo)記為deprecated。
thissuper關(guān)鍵字的用法
this是指向?qū)ο蟊旧淼囊粋€(gè)指針。
this的用法在java中大體可以分為3種:
普通的直接引用,this相當(dāng)于是指向當(dāng)前對(duì)象本身。
當(dāng)形參與成員名字重名,用this來(lái)辨別
引用本類的構(gòu)造函數(shù)
super可以理解為是指向自己父類對(duì)象的一個(gè)指針,而這個(gè)超類指的是離自己最近的一個(gè)父類。
super也有三種用法:
普通的直接引用,super相當(dāng)于是指向當(dāng)前對(duì)象的父類引用,這樣就可以用super.xxx來(lái)引用父類的成員。
當(dāng)子類中的成員變量或辦法與父類中的成員變量或辦法同名時(shí),用super進(jìn)行辨別
引用父類構(gòu)造函數(shù)
static存在的主要意義
static的主要意義是在于創(chuàng)立獨(dú)立于具體對(duì)象的變量或者辦法。即使沒(méi)有創(chuàng)立對(duì)象,也能使用屬性和調(diào)用辦法!
static關(guān)鍵字還有一個(gè)比擬關(guān)鍵的作用就是用來(lái)形成靜態(tài)代碼塊來(lái)優(yōu)化程序性能。static塊可以置于類中的任何地方,類中可以有多個(gè)static塊。在類初次被加載的時(shí)候,會(huì)按照static塊的順序來(lái)執(zhí)行每個(gè)static塊,并且只會(huì)執(zhí)行一次。因此,很多時(shí)候會(huì)將一些只需要進(jìn)行一次初始化的操作放在static代碼塊中。
break,continue,return的區(qū)別及作用
break結(jié)束當(dāng)前的循環(huán)體
continue跳出本次循環(huán),繼續(xù)執(zhí)行下次循環(huán)-
return結(jié)束當(dāng)前的辦法,直接返回
面向?qū)ο?/p>
面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別
面向過(guò)程:
優(yōu)點(diǎn):性能比面向?qū)ο蟾?,因?yàn)轭愓{(diào)用時(shí)需要實(shí)例化,開(kāi)銷比擬大,比擬耗費(fèi)資源;比方單片機(jī)、嵌入式開(kāi)發(fā)、Linux/Unix等一般采用面向過(guò)程開(kāi)發(fā),性能是最重要的因素。
缺點(diǎn):沒(méi)有面向?qū)ο笠拙S護(hù)、易復(fù)用、易擴(kuò)展
面向?qū)ο螅?/p>
優(yōu)點(diǎn):易維護(hù)、易復(fù)用、易擴(kuò)展,由于面向?qū)ο笥蟹庋b、繼承、多態(tài)性的特性,可以設(shè)計(jì)出低耦合的系統(tǒng),使系統(tǒng)更加靈活、更加易于維護(hù)
缺點(diǎn):性能比面向過(guò)程低
面向過(guò)程是具體化的,流程化的,解決一個(gè)問(wèn)題,你需要一步一步的分析,一步一步的實(shí)現(xiàn)
面向?qū)ο笫浅橄蠡?,模型化的,你只需抽象出一個(gè)類,這是一個(gè)封閉的盒子,在這里你擁有數(shù)據(jù)也擁有解決問(wèn)題的辦法。需要什么功能直接使用就可以了,不必去一步一步的實(shí)現(xiàn),至于這個(gè)功能是如何實(shí)現(xiàn)的,我們可以不用太關(guān)懷,會(huì)用就可以了
面向?qū)ο蟮牡讓悠鋵?shí)還是面向過(guò)程,把面向過(guò)程抽象成類,然后封裝,方便我們使用的就是面向?qū)ο罅恕?/p>
@$面向?qū)ο笕筇匦?/p>
面向?qū)ο蟮奶卣髦饕邢铝袔讉€(gè)方面:
抽象:抽象是將一類對(duì)象的共同特征總結(jié)出來(lái)構(gòu)造類的過(guò)程,包括數(shù)據(jù)抽象和行為抽象兩方面。抽象只關(guān)注對(duì)象有哪些屬性和行為,并不關(guān)注這些行為的細(xì)節(jié)是什么。
其中Java面向?qū)ο缶幊倘筇匦裕悍庋b繼承多態(tài)
封裝:封裝是把一個(gè)對(duì)象的屬性私有化,隱藏內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),同時(shí)提供一些可以被外界訪問(wèn)屬性的辦法。通過(guò)封裝可以使程序便于使用,提高復(fù)用性和平安性
繼承:繼承是使用已存在的類的定義作為根底,建立新類的技術(shù),新類的定義可以增加新的數(shù)據(jù)或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過(guò)繼承可以提高代碼復(fù)用性。繼承是多態(tài)的前提。
關(guān)于繼承如下3點(diǎn)請(qǐng)記住
子類擁有父類非private的屬性和辦法。
子類可以擁有自己的屬性和辦法,即子類可以對(duì)父類進(jìn)行擴(kuò)展。
子類可以用自己的方式實(shí)現(xiàn)父類的辦法。
多態(tài)性:父類或接口定義的引用變量可以指向子類或具體實(shí)現(xiàn)類的實(shí)例對(duì)象。多態(tài)提高了程序的擴(kuò)展性。一個(gè)引用變量到底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的辦法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的辦法,必須在程序運(yùn)行期間才能決定。
Java實(shí)現(xiàn)多態(tài)有三個(gè)必要條件:繼承、重寫、向上轉(zhuǎn)型。
繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類。
重寫:子類對(duì)父類中某些辦法進(jìn)行重新定義,在調(diào)用這些辦法時(shí)就會(huì)調(diào)用子類的辦法。
向上轉(zhuǎn)型:在多態(tài)中需要將子類的引用賦給父類對(duì)象,只有這樣該引用才能夠具備調(diào)用父類和子類的辦法的技能。
只有滿足了上述三個(gè)條件,我們才能夠在同一個(gè)繼承結(jié)構(gòu)中使用統(tǒng)一的邏輯實(shí)現(xiàn)代碼處理不同的對(duì)象,從而到達(dá)執(zhí)行不同的行為。
@$抽象類和接口的比照
抽象類是用來(lái)捕捉子類的通用特性的,實(shí)現(xiàn)代碼重用。接口是抽象辦法的匯合,利用接口可以到達(dá)API定義和實(shí)現(xiàn)別離的目的,提供程序的擴(kuò)展性和可維護(hù)性。
從設(shè)計(jì)層面來(lái)說(shuō),抽象類是對(duì)類的抽象,是一種模板設(shè)計(jì),接口是行為的抽象,是一種行為的標(biāo)準(zhǔn)。
相同點(diǎn)
接口和抽象類都不能實(shí)例化
都位于繼承的頂端,用于被其他類實(shí)現(xiàn)或繼承
都包含抽象辦法,其子類都必須重寫這些抽象辦法
不同點(diǎn)
參數(shù) 抽象類 接口
聲明 抽象類使用abstract關(guān)鍵字聲明 接口使用interface關(guān)鍵字聲明
實(shí)現(xiàn) 子類使用extends關(guān)鍵字來(lái)繼承抽象類。如果一個(gè)類繼承了抽象類,則該子類必須實(shí)現(xiàn)抽象類的所有抽象辦法。 子類使用implements關(guān)鍵字來(lái)實(shí)現(xiàn)接口。如果一個(gè)類實(shí)現(xiàn)了接口,則該子類必須實(shí)現(xiàn)父接口的所有辦法。
構(gòu)造器 抽象類可以有構(gòu)造器 接口不能有構(gòu)造器
訪問(wèn)修飾符 抽象類中的辦法可以是任意訪問(wèn)修飾符 接口辦法默認(rèn)修飾符是public。并且不允許定義為private或者protected
字段聲明 抽象類的字段聲明可以是任意的 接口的字段默認(rèn)都是static和final的
多繼承 一個(gè)類最多只能繼承一個(gè)抽象類 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
備注:Java8中接口中引入默認(rèn)辦法和靜態(tài)辦法,以此來(lái)減少抽象類和接口之間的差別?,F(xiàn)在,我們可以為接口提供默認(rèn)實(shí)現(xiàn)的辦法了,并且不用強(qiáng)制子類來(lái)實(shí)現(xiàn)它。
接口和抽象類各有優(yōu)缺點(diǎn),在接口和抽象類的選擇上,必須遵守下面的幾個(gè)原那么:
抽象類用來(lái)定義某個(gè)領(lǐng)域的固有屬性,即抽象類表示它是什么,接口用來(lái)定義某個(gè)領(lǐng)域的擴(kuò)展功能,即接口表示它能做什么。
當(dāng)需要為子類提供公共的實(shí)現(xiàn)代碼時(shí),應(yīng)優(yōu)先考慮抽象類。因?yàn)槌橄箢愔械姆浅橄筠k法可以被子類繼承,使實(shí)現(xiàn)功能的代碼更簡(jiǎn)潔。
當(dāng)注重代碼的擴(kuò)展性和可維護(hù)性時(shí),應(yīng)當(dāng)優(yōu)先采用接口。①接口與實(shí)現(xiàn)類之間可以不存在任何層次關(guān)系,接口可以實(shí)現(xiàn)毫不相關(guān)類的行為,比抽象類的使用更加方便靈活;②接口只關(guān)懷對(duì)象之間的交互辦法,而不關(guān)懷對(duì)象所對(duì)應(yīng)的具體類。接口是程序之間的一個(gè)協(xié)議,比抽象類的使用更平安、清晰。一般使用接口的情況更多。
@$成員變量與部分變量的區(qū)別有哪些
變量:在程序執(zhí)行的過(guò)程中,其值可以在某個(gè)范圍內(nèi)發(fā)生改變的量。從本質(zhì)上講,變量其實(shí)是內(nèi)存中的一小塊區(qū)域
各變量聯(lián)系與區(qū)別
成員變量:作用范圍是整個(gè)類,相當(dāng)于C中的全局變量,定義在辦法體和語(yǔ)句塊之外,一般定義在類的聲明之下;成員變量包括實(shí)例變量和靜態(tài)變量(類變量);
實(shí)例變量:獨(dú)立于與辦法之外的變量,無(wú)static修飾,聲明在一個(gè)類中,但在辦法、構(gòu)造辦法和語(yǔ)句塊之外,數(shù)值型變量默認(rèn)值為0,布爾型默認(rèn)值為false,引用類型默認(rèn)值為null;
靜態(tài)變量(類變量):獨(dú)立于辦法之外的變量,用static修飾,默認(rèn)值與實(shí)例變量相似,一個(gè)類中只有一份,屬于對(duì)象共有,存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū),經(jīng)常被聲明為常量,調(diào)用一般是類名.靜態(tài)變量名,也可以用對(duì)象名.靜態(tài)變量名調(diào)用;
部分變量:類的辦法中的變量,訪問(wèn)修飾符不能用于部分變量,聲明在辦法、構(gòu)造辦法或語(yǔ)句塊中,在棧上分配,無(wú)默認(rèn)值,必須初始化后才能使用;
成員變量和部分變量的區(qū)別
成員變量 部分變量
作用域 作用范圍是整個(gè)類 在辦法或者語(yǔ)句塊內(nèi)有效
存儲(chǔ)位置和生命周期 隨著對(duì)象的創(chuàng)立而存在,隨著對(duì)象的消失而消失,存儲(chǔ)在堆內(nèi)存中 在辦法被調(diào)用的時(shí)候存在,辦法調(diào)用完會(huì)自動(dòng)釋放,存儲(chǔ)在棧內(nèi)存中
初始值 有默認(rèn)初始值 沒(méi)有默認(rèn)初始值,使用前必須賦值
使用原那么 就近原那么,首先在部分位置找,有就使用;接著在成員位置找
@$重載〔Overload〕和重寫〔Override〕的區(qū)別。重載的辦法能否根據(jù)返回類型進(jìn)行辨別?
辦法的重載和重寫都是實(shí)現(xiàn)多態(tài)的方式,區(qū)別在于前者實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性,而后者實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性。
重載:發(fā)生在同一個(gè)類中,辦法名相同參數(shù)列表不同〔參數(shù)類型不同、個(gè)數(shù)不同、順序不同〕,與辦法返回值和訪問(wèn)修飾符無(wú)關(guān),即重載的辦法不能根據(jù)返回類型進(jìn)行辨別
重寫:發(fā)生在父子類中,辦法名、參數(shù)列表必須相同,返回值小于等于父類,拋出的異常小于等于父類,訪問(wèn)修飾符大于等于父類〔里氏代換原那么〕;如果父類辦法訪問(wèn)修飾符為private那么子類中就不是重寫。
@$==和equals的區(qū)別是什么
==:它的作用是判斷兩個(gè)對(duì)象的內(nèi)存地址是不是相等。即,判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象。(根本數(shù)據(jù)類型==比擬的是值,引用數(shù)據(jù)類型==比擬的是內(nèi)存地址)
equals():它的作用也是判斷兩個(gè)對(duì)象是否相等。有兩種使用情況:
情況1:類沒(méi)有覆蓋equals()辦法,等價(jià)于通過(guò)“==〞比擬這兩個(gè)對(duì)象。
情況2:類覆蓋了equals()辦法。一般我們都覆蓋equals()辦法來(lái)判斷兩個(gè)對(duì)象的內(nèi)容相等;假設(shè)它們的內(nèi)容相等,那么返回true(即,認(rèn)為這兩個(gè)對(duì)象相等)。
舉個(gè)例子
publicclasstest1{
publicstaticvoidmain(String[]args){
Stringa=newString("ab");//a為一個(gè)引用
Stringb=newString("ab");//b為另一個(gè)引用,對(duì)象的內(nèi)容一樣
Stringaa="ab";//放在常量池中
Stringbb="ab";//從常量池中查找
if(aa==bb)//true
System.out.println("aa==bb");
if(a==b)//false,非同一對(duì)象
System.out.println("a==b");
if(a.equals(b))//true
System.out.println("aEQb");
if(42==42.0){//true
System.out.println("true");
}
}
}
表明:
String中的equals辦法是被重寫過(guò)的,因?yàn)閛bject的equals辦法是比擬的對(duì)象的內(nèi)存地址,而String的equals辦法比擬的是對(duì)象的值。
當(dāng)創(chuàng)立String類型的對(duì)象時(shí),虛擬時(shí)機(jī)在常量池中查找有沒(méi)有已經(jīng)存在的值和要?jiǎng)?chuàng)立的值相同的對(duì)象,如果有就把它賦給當(dāng)前引用。如果沒(méi)有就在常量池中重新創(chuàng)立一個(gè)String對(duì)象。
@$hashCode與equals
hashCode()介紹
hashCode()的作用是獲取哈希碼,也稱為散列碼;它實(shí)際上是返回一個(gè)int類型的整數(shù)。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置。hashCode()定義在JDK的Object類中,這就意味著Java中的任何類都包含有hashCode()函數(shù)。
散列表存儲(chǔ)的是鍵值對(duì)(key-value),它的特點(diǎn)是:能根據(jù)“鍵〞快速的檢索出對(duì)應(yīng)的“值〞。這其中就利用到了散列碼!〔可以快速找到所需要的對(duì)象〕
為什么要有hashCode
我們以“HashSet如何檢查重復(fù)〞為例子來(lái)表明為什么要有hashCode:
當(dāng)你把對(duì)象參加HashSet時(shí),HashSet會(huì)先計(jì)算對(duì)象的hashcode值來(lái)判斷對(duì)象參加的位置,同時(shí)也會(huì)與其他已經(jīng)參加的對(duì)象的hashcode值作比擬,如果沒(méi)有相同的hashcode,HashSet會(huì)若對(duì)象沒(méi)有重復(fù)出現(xiàn)。但是如果發(fā)現(xiàn)有相同hashcode值的對(duì)象,這時(shí)會(huì)調(diào)用equals()辦法來(lái)檢查hashcode相等的對(duì)象是否真的相同。如果兩者相同,HashSet就不會(huì)讓其參加操作成功。如果不同的話,就會(huì)重新散列到其他位置。
先進(jìn)行hashcode比擬,后進(jìn)行equals辦法比擬的目的:可以大大減少了equals辦法比擬的次數(shù),相應(yīng)就大大提高了執(zhí)行速度。
hashCode()與equals()的相關(guān)規(guī)定
如果兩個(gè)對(duì)象相等,那么hashcode一定也是相同的
兩個(gè)對(duì)象相等,對(duì)兩個(gè)對(duì)象分別調(diào)用equals辦法都返回true
兩個(gè)對(duì)象有相同的hashcode值,它們不一定是相等的
因此,當(dāng)重寫equals辦法后有必要將hashCode辦法也重寫,這樣做才能保證不違背hashCode辦法中“相同對(duì)象必須有相同哈希值〞的約定。
值傳遞和引用傳遞有什么區(qū)別
值傳遞,按值調(diào)用(callbyvalue):指的是在辦法調(diào)用時(shí),傳遞的參數(shù)是值的拷貝,傳遞后就互不相關(guān)了。
引用傳遞,引用調(diào)用〔callbyreference):指的是在辦法調(diào)用時(shí),傳遞的參數(shù)是引用變量所對(duì)應(yīng)的內(nèi)存地址。傳遞前和傳遞后都指向同一個(gè)引用〔也就是同一個(gè)內(nèi)存空間〕。
一個(gè)辦法可以修改引用傳遞所對(duì)應(yīng)的變量值,而不能修改值傳遞所對(duì)應(yīng)的變量值
為什么Java中只有值傳遞
Java采用按值調(diào)用。也就是說(shuō),辦法得到的是所有參數(shù)值的一個(gè)拷貝,也就是說(shuō),辦法不能修改傳遞給它的任何參數(shù)變量的內(nèi)容。
下面通過(guò)3個(gè)例子來(lái)給大家表明
example1
publicstaticvoidmain(String[]args){
intnum1=10;
intnum2=20;
swap(num1,num2);
System.out.println("num1="+num1);
System.out.println("num2="+num2);
}
publicstaticvoidswap(inta,intb){
inttemp=a;
a=b;
b=temp;
System.out.println("a="+a);
System.out.println("b="+b);
}
結(jié)果:
a=20
b=10
num1=10
num2=20
解析:
在swap辦法中,a、b的值進(jìn)行交換,并不會(huì)影響到num1、num2。因?yàn)閍、b中的值,只是從num1、num2的復(fù)制過(guò)來(lái)的。也就是說(shuō),a、b相當(dāng)于num1、num2的副本,副本的內(nèi)容無(wú)論怎么修改,都不會(huì)影響到原件本身。
通過(guò)上面例子,我們已經(jīng)知道了一個(gè)辦法不能修改一個(gè)根本數(shù)據(jù)類型的參數(shù),而對(duì)象引用作為參數(shù)就不一樣,請(qǐng)看example2.
example2
publicstaticvoidmain(String[]args){
int[]arr={1,2,3,4,5};
System.out.println(arr[0]);
change(arr);
System.out.println(arr[0]);
}
publicstaticvoidchange(int[]array){
//將數(shù)組的第一個(gè)元素變?yōu)?
array[0]=0;
}
結(jié)果:
1
0
解析:
array被初始化arr的拷貝也就是一個(gè)對(duì)象的引用,也就是說(shuō)array和arr指向的時(shí)同一個(gè)數(shù)組對(duì)象。因此,外部對(duì)引用對(duì)象的改變會(huì)反映到所對(duì)應(yīng)的對(duì)象上。
通過(guò)example2我們已經(jīng)看到,實(shí)現(xiàn)一個(gè)改變對(duì)象參數(shù)狀態(tài)的辦法并不是一件難事。理由很簡(jiǎn)單,辦法得到的是對(duì)象引用的拷貝,對(duì)象引用及其他的拷貝同時(shí)引用同一個(gè)對(duì)象。
很多程序設(shè)計(jì)語(yǔ)言〔特別是,C++和Pascal)提供了兩種參數(shù)傳遞的方式:值調(diào)用和引用調(diào)用。有些程序員〔甚至本書(shū)的作者〕認(rèn)為Java程序設(shè)計(jì)語(yǔ)言對(duì)對(duì)象采用的是引用調(diào)用,實(shí)際上,這種理解是不對(duì)的。由于這種誤解具有一定的普遍性,所下列面給出一個(gè)反例來(lái)詳細(xì)地闡述一下這個(gè)問(wèn)題。
example3
publicclassTest{
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
Students1=newStudent("小張");
Students2=newStudent("小李");
Test.swap(s1,s2);
System.out.println("s1:"+s1.getName());
System.out.println("s2:"+s2.getName());
}
publicstaticvoidswap(Studentx,Studenty){
Studenttemp=x;
x=y;
y=temp;
System.out.println("x:"+x.getName());
System.out.println("y:"+y.getName());
}
}
結(jié)果:
x:小李
y:小張
s1:小張
s2:小李
解析:
交換之前:
交換之后:
通過(guò)上面兩張圖可以很清晰的看出:辦法并沒(méi)有改變存儲(chǔ)在變量s1和s2中的對(duì)象引用。swap辦法的參數(shù)x和y被初始化為兩個(gè)對(duì)象引用的拷貝,這個(gè)辦法交換的是這兩個(gè)拷貝
總結(jié)
Java對(duì)對(duì)象采用的不是引用調(diào)用,實(shí)際上,對(duì)象引用是按值傳遞的。
下面再總結(jié)一下Java中辦法參數(shù)的使用情況:
一個(gè)辦法不能修改一個(gè)根本數(shù)據(jù)類型的參數(shù)〔即數(shù)值型或布爾型〕
一個(gè)辦法可以改變一個(gè)對(duì)象參數(shù)的狀態(tài)。
一個(gè)辦法不能讓對(duì)象參數(shù)引用一個(gè)新的對(duì)象。
IO流
java中IO流分為幾種《
按照流的流向分,可以分為輸入流和輸出流;
按照操作單元?jiǎng)澐?,可以分為字?jié)流和字符流;
按照流的角色劃分,可以分為節(jié)點(diǎn)流和處理流。
JavaIO流共波及40多個(gè)類,這些類看上去很雜亂,但實(shí)際上很有規(guī)那么,而且彼此之間存在非常緊密的聯(lián)系,JavaIO流的40多個(gè)類大局部都是從如下4個(gè)抽象類基類中派生出來(lái)的。
InputStream/Reader:所有的輸入流的基類,前者是字節(jié)輸入流,后者是字符輸入流。
OutputStream/Writer:所有輸出流的基類,前者是字節(jié)輸出流,后者是字符輸出流。
@$BIO,NIO,AIO有什么區(qū)別《
在講BIO,NIO,AIO之前先來(lái)回憶一下這樣幾個(gè)概念:同步與異步,阻塞與非阻塞。
同步與異步
同步:同步就是發(fā)起一個(gè)請(qǐng)求,被調(diào)用者未處理完請(qǐng)求之前,調(diào)用不返回。
異步:異步就是發(fā)起一個(gè)請(qǐng)求,立刻得到被調(diào)用者的響應(yīng)表示已接收到請(qǐng)求,但是被調(diào)用者并沒(méi)有返回請(qǐng)求處理結(jié)果,此時(shí)我們可以處理其他的請(qǐng)求,被調(diào)用者通過(guò)事件和回調(diào)等機(jī)制來(lái)通知調(diào)用者其返回結(jié)果。
同步和異步的區(qū)別在于調(diào)用者需不需要等待被調(diào)用者的處理結(jié)果。
阻塞和非阻塞
阻塞:阻塞就是發(fā)起一個(gè)請(qǐng)求,調(diào)用者一直等待請(qǐng)求結(jié)果返回,也就是當(dāng)前線程會(huì)被掛起,無(wú)法從事其他任務(wù),只有當(dāng)返回結(jié)果才能繼續(xù)。
非阻塞:非阻塞就是發(fā)起一個(gè)請(qǐng)求,調(diào)用者不用一直等著結(jié)果返回,可以先去干其他事情。
阻塞和非阻塞的區(qū)別在于調(diào)用者的線程需不需要掛起。
JavaIO方式有很多種,基于不同的IO抽象模型和交互方式,可以進(jìn)行簡(jiǎn)單辨別。
BIO〔jdk1.4之前〕:BlockIO同步阻塞式IO,就是我們平常使用的傳統(tǒng)IO,它基于流模型實(shí)現(xiàn),一個(gè)連接一個(gè)線程,客戶端有連接請(qǐng)求時(shí),效勞器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理,線程開(kāi)銷大。偽異步IO:將請(qǐng)求連接放入線程池,一對(duì)多,但線程還是很珍貴的資源。它的特點(diǎn)是模式簡(jiǎn)單使用方便,但并發(fā)處理能力低,容易成為應(yīng)用性能的瓶頸。BIO是面向流的,BIO的Stream是單向的。
很多時(shí)候,人們也把包下的局部網(wǎng)絡(luò)API,比方Socket、ServerSocket、HttpURLConnection也歸類到同步阻塞IO,因?yàn)榫W(wǎng)絡(luò)通信同樣是IO行為。
NIO〔jdk1.4之后
linux的多路復(fù)用技術(shù)select模式〕:NonIO同步非阻塞IO,是傳統(tǒng)IO的升級(jí),提供了Channel、Selector、Buffer等新的抽象,客戶端和效勞器端通過(guò)Channel〔通道〕通訊,實(shí)現(xiàn)了多路復(fù)用??蛻舳税l(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器上,多路復(fù)用器輪詢到連接有I/O請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。Mina2.0和Netty5.0網(wǎng)絡(luò)通信框架都是通過(guò)NIO實(shí)現(xiàn)的網(wǎng)絡(luò)通信。NIO是面向緩沖區(qū)的,NIO的channel是雙向的。
NIO能解決什么問(wèn)題?
通過(guò)一個(gè)固定大小的線程池,來(lái)負(fù)責(zé)管理工作線程,防止頻繁創(chuàng)立、銷毀線程的開(kāi)銷,這是我們構(gòu)建并發(fā)效勞的典型方式。
NIO那么是利用了單線程輪詢事件的機(jī)制,通過(guò)高效地定位就緒的Channel,來(lái)決定做什么,僅僅select階段是阻塞的,可以有效防止大量客戶端連接時(shí),頻繁線程切換帶來(lái)的問(wèn)題,應(yīng)用的擴(kuò)展能力有了非常大的提高。
AIO〔jdk
1.7過(guò)后又叫NIO2〕:AsynchronousIO異步非梗塞IO,是NIO的升級(jí),異步IO的操作基于事件和回調(diào)機(jī)制,性能是最好的。底層實(shí)現(xiàn)是通過(guò)epoll的I/O多路復(fù)用機(jī)制。
BIO、NIO、AIO實(shí)現(xiàn)原理
BIO實(shí)現(xiàn)原理
BIO模型是最早的jdk提供的一種處理網(wǎng)絡(luò)連接請(qǐng)求的模型,是同步阻塞結(jié)構(gòu),通常由一個(gè)獨(dú)立的Acceptor線程負(fù)責(zé)監(jiān)聽(tīng)客戶端的連接,它接收到客戶端連接請(qǐng)求之后為每個(gè)客戶端創(chuàng)立一個(gè)新的線程進(jìn)行鏈路處理,處理完成后,通過(guò)輸出流返回應(yīng)答給客戶端,線程銷毀。即典型的一請(qǐng)求一應(yīng)答模型。
BIO是同步阻塞式IO,通常在while循環(huán)中效勞端會(huì)調(diào)用accept辦法等待接收客戶端的連接請(qǐng)求,一旦接收到一個(gè)連接請(qǐng)求,就可以建立通信套接字在這個(gè)通信套接字上進(jìn)行讀寫操作,此時(shí)不能再接收其他客戶端連接請(qǐng)求,只能等待同當(dāng)前連接的客戶端的操作執(zhí)行完成。
如果BIO要能夠同時(shí)處理多個(gè)客戶端請(qǐng)求,就必須使用多線程,即每次accept阻塞等待來(lái)自客戶端請(qǐng)求,一旦受到連接請(qǐng)求就建立通信套接字同時(shí)開(kāi)啟一個(gè)新的線程來(lái)處理這個(gè)套接字的數(shù)據(jù)讀寫請(qǐng)求,然后立刻又繼續(xù)accept等待其他客戶端連接請(qǐng)求,即為每一個(gè)客戶端連接請(qǐng)求都創(chuàng)立一個(gè)線程來(lái)獨(dú)自處理。
NIO實(shí)現(xiàn)原理
nio模型事件處理流程:
Acceptor注冊(cè)Selector,監(jiān)聽(tīng)accept事件;
當(dāng)客戶端連接后,觸發(fā)accept事件;
效勞器構(gòu)建對(duì)應(yīng)的Channel,并在其上注冊(cè)Selector,監(jiān)聽(tīng)讀寫事件;
當(dāng)發(fā)生讀寫事件后,進(jìn)行相應(yīng)的讀寫處理。
NIO本身是基于事件驅(qū)動(dòng)思想來(lái)完成的,其主要想解決的是BIO的大并發(fā)問(wèn)題,即在使用同步I/O的網(wǎng)絡(luò)應(yīng)用中,如果要同時(shí)處理多個(gè)客戶端請(qǐng)求,或是在客戶端要同時(shí)和多個(gè)效勞器進(jìn)行通訊,就必須使用多線程來(lái)處理。也就是說(shuō),將每一個(gè)客戶端請(qǐng)求分配給一個(gè)線程來(lái)獨(dú)自處理。這樣做雖然可以到達(dá)我們的要求,但同時(shí)又會(huì)帶來(lái)另外一個(gè)問(wèn)題。由于每創(chuàng)立一個(gè)線程,就要為這個(gè)線程分配一定的內(nèi)存空間〔也叫工作存儲(chǔ)器〕,而且操作系統(tǒng)本身也對(duì)線程的總數(shù)有一定的限制。如果客戶端的請(qǐng)求過(guò)多,效勞端程序可能會(huì)因?yàn)椴豢爸刎?fù)而拒絕客戶端的請(qǐng)求,甚至效勞器可能會(huì)因此而癱瘓。
NIO基于Reactor,當(dāng)selector有流可讀或可寫入socket時(shí),操作系統(tǒng)會(huì)相應(yīng)的通知應(yīng)用程序進(jìn)行處理,應(yīng)用再將流讀取到緩沖區(qū)或?qū)懭氩僮飨到y(tǒng)。
也就是說(shuō),這個(gè)時(shí)候,已經(jīng)不是一個(gè)連接就要對(duì)應(yīng)一個(gè)處理線程了,而是有效的請(qǐng)求,對(duì)應(yīng)一個(gè)線程,當(dāng)連接沒(méi)有數(shù)據(jù)時(shí),是沒(méi)有工作線程來(lái)處理的。
Reactor單線程模型
這是最簡(jiǎn)單的單Reactor單線程模型。Reactor線程負(fù)責(zé)多路別離套接字、accept新連接,并分派請(qǐng)求到處理器鏈中。該模型適用于處理器鏈中業(yè)務(wù)處理組件能快速完成的場(chǎng)景。不過(guò),這種單線程模型不能充沛利用多核資源,所以實(shí)際使用的不多。
這個(gè)模型和上面的NIO流程很類似,只是將消息相關(guān)處理獨(dú)立到了Handler中去了。
雖然上面說(shuō)到NIO一個(gè)線程就可以支持所有的IO處理。但是瓶頸也是顯而易見(jiàn)的。我們看一個(gè)客戶端的情況,如果這個(gè)客戶端屢次進(jìn)行請(qǐng)求,如果在Handler中的處理速度較慢,則后續(xù)的客戶端請(qǐng)求都會(huì)被積壓,導(dǎo)致響應(yīng)變慢!所以引入了Reactor多線程模型。
Reactor多線程模型
相比上一種模型,該模型在處理器鏈局部采用了多線程〔線程池〕:
Reactor多線程模型就是將Handler中的IO操作和非IO操作分開(kāi),操作IO的線程稱為IO線程,非IO操作的線程稱為工作線程。這樣的話,客戶端的請(qǐng)求會(huì)直接被丟到線程池中,客戶端發(fā)送請(qǐng)求就不會(huì)梗塞。
但是當(dāng)用戶進(jìn)一步增加的時(shí)候,Reactor會(huì)出現(xiàn)瓶頸!因?yàn)镽eactor既要處理IO操作請(qǐng)求,又要響應(yīng)連接請(qǐng)求。為了分擔(dān)Reactor的負(fù)擔(dān),所以引入了主從Reactor模型。
主從Reactor多線程模型
主從Reactor多線程模型是將Reactor分成兩局部,mainReactor負(fù)責(zé)監(jiān)聽(tīng)serversocket,accept新連接,并將建立的socket分派給subReactor。subReactor負(fù)責(zé)多路別離已連接的socket,讀寫網(wǎng)絡(luò)數(shù)據(jù),對(duì)業(yè)務(wù)處理功能,其扔給worker線程池完成。通常,subReactor個(gè)數(shù)上可與CPU個(gè)數(shù)等同:
可見(jiàn),主Reactor用于響應(yīng)連接請(qǐng)求,從Reactor用于處理IO操作請(qǐng)求。
AIO
與NIO不同,當(dāng)進(jìn)行讀寫操作時(shí),只須直接調(diào)用API的read或write辦法即可。這兩種辦法均為異步的,對(duì)于讀操作而言,當(dāng)有流可讀取時(shí),操作系統(tǒng)會(huì)將可讀的流傳入read辦法的緩沖區(qū),并通知應(yīng)用程序;對(duì)于寫操作而言,當(dāng)操作系統(tǒng)將write辦法傳遞的流寫入完畢時(shí),操作系統(tǒng)主動(dòng)通知應(yīng)用程序。
AIO是一種接口規(guī)范,各家操作系統(tǒng)可以實(shí)現(xiàn)也可以不實(shí)現(xiàn)。在不同操作系統(tǒng)上在高并發(fā)情況下最好都采用操作系統(tǒng)推薦的方式。Linux上還沒(méi)有真正實(shí)現(xiàn)網(wǎng)絡(luò)方式的AIO。
異步IO那么采用“訂閱-通知〞模式:即應(yīng)用程序向操作系統(tǒng)注冊(cè)IO監(jiān)聽(tīng),然后繼續(xù)做自己的事情。當(dāng)操作系統(tǒng)發(fā)生IO事件,并且準(zhǔn)備好數(shù)據(jù)后,在主動(dòng)通知應(yīng)用程序,觸發(fā)相應(yīng)的函數(shù)。也可以如圖所示理解:
和同步IO一樣,異步IO也是由操作系統(tǒng)進(jìn)行支持的。微軟的windows系統(tǒng)提供了一種異步IO技術(shù):IOCP〔I/OCompletionPort,I/O完成端口〕;Linux下由于沒(méi)有這種異步IO技術(shù),所以使用的是epoll對(duì)異步IO進(jìn)行模擬。
反射
什么是反射機(jī)制?
JAVA反射機(jī)制是在程序運(yùn)行過(guò)程中,對(duì)于任意一個(gè)類或?qū)ο?,都能夠知道這個(gè)類或?qū)ο蟮乃袑傩院娃k法,這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象辦法的功能稱為java語(yǔ)言的反射機(jī)制。
靜態(tài)編譯和動(dòng)態(tài)編譯
靜態(tài)編譯:在編譯時(shí)確定類型,綁定對(duì)象
動(dòng)態(tài)編譯:在運(yùn)行時(shí)確定類型,綁定對(duì)象
反射機(jī)制優(yōu)缺點(diǎn)
優(yōu)點(diǎn):運(yùn)行期類型的判斷,動(dòng)態(tài)加載類,提高代碼的靈活性。
缺點(diǎn):性能瓶頸:反射相當(dāng)于一系列解釋操作,通知JVM要做的事情,性能比直接的java代碼要慢很多。
@$反射為什么慢
反射調(diào)用過(guò)程中會(huì)產(chǎn)生大量的臨時(shí)對(duì)象,這些對(duì)象會(huì)占用內(nèi)存,可能會(huì)導(dǎo)致頻繁gc,從而影響性能。
反射調(diào)用辦法時(shí)會(huì)從辦法數(shù)組中遍歷查找,并且檢查可見(jiàn)性等操作會(huì)比擬耗時(shí)。
反射在到達(dá)一定次數(shù)時(shí),會(huì)動(dòng)態(tài)編寫字節(jié)碼并加載到內(nèi)存中,這個(gè)字節(jié)碼沒(méi)有經(jīng)過(guò)編譯器優(yōu)化,也不能享受JIT優(yōu)化。
反射一般會(huì)波及自動(dòng)裝箱/拆箱和類型轉(zhuǎn)換,都會(huì)帶來(lái)一定的資源開(kāi)銷。
反射機(jī)制的應(yīng)用場(chǎng)景有哪些?
反射是框架設(shè)計(jì)的靈魂。
在我們平時(shí)的工程開(kāi)發(fā)過(guò)程中,根本上很少會(huì)直接使用到反射機(jī)制,但這不能表明反射機(jī)制沒(méi)有用,實(shí)際上有很多設(shè)計(jì)、開(kāi)發(fā)都與反射機(jī)制有關(guān),示例模塊化的開(kāi)發(fā),通過(guò)反射去調(diào)用對(duì)應(yīng)的字節(jié)碼;動(dòng)態(tài)代理設(shè)計(jì)模式也采用了反射機(jī)制,還有我們?nèi)粘J褂玫腟pring/Hibernate等框架也大量使用到了反射機(jī)制。
舉例:①我們?cè)谑褂肑DBC連接數(shù)據(jù)庫(kù)時(shí)使用Class.forName()通過(guò)反射加載數(shù)據(jù)庫(kù)的驅(qū)動(dòng)程序;②Spring框架也用到很多反射機(jī)制,最經(jīng)典的就是xml的配置模式。Spring通過(guò)XML配置模式裝載Bean的過(guò)程:1)將程序內(nèi)所有XML或Properties配置文件加載入內(nèi)存中;2)Java類里面解析xml或properties里面的內(nèi)容,得到對(duì)應(yīng)實(shí)體類的字節(jié)碼字符串以及相關(guān)的屬性信息;3)使用反射機(jī)制,根據(jù)這個(gè)字符串獲得某個(gè)類的Class實(shí)例;4)動(dòng)態(tài)配置實(shí)例的屬性
網(wǎng)絡(luò)編程
TCP/IP的五層體系結(jié)構(gòu)分別是什么?
應(yīng)用層
應(yīng)用層(application-layer〕的任務(wù)是通過(guò)應(yīng)用進(jìn)程間的交互來(lái)完成特定網(wǎng)絡(luò)應(yīng)用。應(yīng)用層協(xié)議定義的是應(yīng)用進(jìn)程間的通信和交互的規(guī)那么。
對(duì)于不同的網(wǎng)絡(luò)應(yīng)用需要不同的應(yīng)用層協(xié)議。在互聯(lián)網(wǎng)中應(yīng)用層協(xié)議很多,如域名系統(tǒng)DNS,支持萬(wàn)維網(wǎng)應(yīng)用的HTTP協(xié)議,支持電子郵件的SMTP協(xié)議等等。
運(yùn)輸層
運(yùn)輸層(transportlayer)的主要任務(wù)就是負(fù)責(zé)向兩臺(tái)主機(jī)進(jìn)程之間的通信提供通用的數(shù)據(jù)傳輸效勞。應(yīng)用進(jìn)程利用該效勞傳送應(yīng)用層報(bào)文。
運(yùn)輸層主要使用一下兩種協(xié)議
傳輸控制協(xié)議-TCP:提供面向連接的,可靠的數(shù)據(jù)傳輸效勞。
用戶數(shù)據(jù)協(xié)議-UDP:提供無(wú)連接的,盡最大努力的數(shù)據(jù)傳輸效勞〔不保證數(shù)據(jù)傳輸?shù)目煽啃浴场?/p>
UDP TCP
是否連接 無(wú)連接 面向連接
是否可靠 不可靠傳輸,不使用流量控制和擁塞控制 可靠傳輸,使用流量控制和擁塞控制
連接對(duì)象個(gè)數(shù) 支持一對(duì)一,一對(duì)多,多對(duì)一和多對(duì)多交互通信 只能是一對(duì)一通信
傳輸方式 面向報(bào)文 面向字節(jié)流
首部開(kāi)銷 首部開(kāi)銷小,僅8字節(jié) 首部最小20字節(jié),最大60字節(jié)
場(chǎng)景 適用于實(shí)時(shí)應(yīng)用〔IP、視頻會(huì)議、直播等〕 適用于要求可靠傳輸?shù)膽?yīng)用,示例文件傳輸
每一個(gè)應(yīng)用層〔TCP/IP參考模型的最高層〕協(xié)議一般都會(huì)使用到兩個(gè)傳輸層協(xié)議之一:
運(yùn)行在TCP協(xié)議上的協(xié)議:
HTTP〔HypertextTransferProtocol,超文本傳輸協(xié)議〕,主要用于普通瀏覽。
HTTPS〔HTTPoverSSL,平安超文本傳輸協(xié)議〕,HTTP協(xié)議的平安版本。
FTP〔FileTransferProtocol,文件傳輸協(xié)議〕,用于文件傳輸。
POP3〔PostOfficeProtocol,version3,郵局協(xié)議〕,收郵件用。
SMTP〔SimpleMailTransferProtocol,簡(jiǎn)單郵件傳輸協(xié)議〕,用來(lái)發(fā)送電子郵件。
TELNET〔TeletypeovertheNetwork,網(wǎng)絡(luò)電傳〕,通過(guò)一個(gè)終端〔terminal〕登陸到網(wǎng)絡(luò)。
SSH〔SecureShell,用于替代平安性差的TELNET〕,用于加密平安登陸用。
運(yùn)行在UDP協(xié)議上的協(xié)議:
BOOTP〔BootProtocol,啟動(dòng)協(xié)議〕,應(yīng)用于無(wú)盤設(shè)備。
NTP〔NetworkTimeProtocol,網(wǎng)絡(luò)時(shí)間協(xié)議〕,用于網(wǎng)絡(luò)同步。
DHCP〔DynamicHostConfigurationProtocol,動(dòng)態(tài)主機(jī)配置協(xié)議〕,動(dòng)態(tài)配置IP地址。
運(yùn)行在TCP和UDP協(xié)議上:
DNS〔DomainNameService,域名效勞〕,用于完成地址查找,郵件轉(zhuǎn)發(fā)等工作。
網(wǎng)絡(luò)層
網(wǎng)絡(luò)層的任務(wù)就是選擇適宜的網(wǎng)間路由和交換結(jié)點(diǎn),確保計(jì)算機(jī)通信的數(shù)據(jù)及時(shí)傳送。在發(fā)送數(shù)據(jù)時(shí),網(wǎng)絡(luò)層把運(yùn)輸層產(chǎn)生的報(bào)文段或用戶數(shù)據(jù)報(bào)封裝成分組和包進(jìn)行傳送。在TCP/IP體系結(jié)構(gòu)中,由于網(wǎng)絡(luò)層使用IP協(xié)議,因此分組也叫IP數(shù)據(jù)報(bào),簡(jiǎn)稱數(shù)據(jù)報(bào)。
互聯(lián)網(wǎng)是由大量的異構(gòu)〔heterogeneous〕網(wǎng)絡(luò)通過(guò)路由器〔router〕相互連接起來(lái)的?;ヂ?lián)網(wǎng)使用的網(wǎng)絡(luò)層協(xié)議是無(wú)連接的網(wǎng)際協(xié)議〔IntertPrococol〕和許多路由選擇協(xié)議,因此互聯(lián)網(wǎng)的網(wǎng)絡(luò)層也叫做網(wǎng)際層或IP層。
數(shù)據(jù)鏈路層
數(shù)據(jù)鏈路層(datalinklayer)通常簡(jiǎn)稱為鏈路層。兩臺(tái)主機(jī)之間的數(shù)據(jù)傳輸,總是在一段一段的鏈路上傳送的,這就需要使用專門的鏈路層的協(xié)議。
在兩個(gè)相鄰節(jié)點(diǎn)之間傳送數(shù)據(jù)時(shí),數(shù)據(jù)鏈路層將網(wǎng)絡(luò)層交下來(lái)的IP數(shù)據(jù)報(bào)組裝成幀,在兩個(gè)相鄰節(jié)點(diǎn)間的鏈路上傳送幀。每一幀包括數(shù)據(jù)和必要的控制信息〔如同步信息,地址信息,過(guò)失控制等〕。
在接收數(shù)據(jù)時(shí),控制信息使接收端能夠知道一個(gè)幀從哪個(gè)比特開(kāi)始和到哪個(gè)比特結(jié)束。
一般的web應(yīng)用的通信傳輸流是這樣的:
發(fā)送端在層與層之間傳輸數(shù)據(jù)時(shí),每經(jīng)過(guò)一層時(shí)會(huì)被打上一個(gè)該層所屬的首部信息。反之,接收端在層與層之間傳輸數(shù)據(jù)時(shí),每經(jīng)過(guò)一層時(shí)會(huì)把對(duì)應(yīng)的首部信息清除。
物理層
在物理層上所傳送的數(shù)據(jù)單位是比特。物理層(physicallayer)的作用是實(shí)現(xiàn)相鄰計(jì)算機(jī)節(jié)點(diǎn)之間比特流的透明傳送,盡可能屏蔽掉具體傳輸介質(zhì)和物理設(shè)備的差別。使其上面的數(shù)據(jù)鏈路層不必考慮網(wǎng)絡(luò)的具體傳輸介質(zhì)是什么?!巴该鱾魉捅忍亓鳕暠硎窘?jīng)實(shí)際電路傳送后的比特流沒(méi)有發(fā)生變化,對(duì)傳送的比特流來(lái)說(shuō),這個(gè)電路好似是看不見(jiàn)的。
四層協(xié)議,五層協(xié)議,七層協(xié)議的區(qū)別
為了使不同體系結(jié)構(gòu)的計(jì)算機(jī)網(wǎng)絡(luò)都能互聯(lián),國(guó)際規(guī)范化組織ISO于1977年提出了一個(gè)試圖使各種計(jì)算機(jī)在世界范圍內(nèi)互聯(lián)成網(wǎng)的規(guī)范框架,即馳名的開(kāi)放系統(tǒng)互聯(lián)根本參考模型OSI/RM,簡(jiǎn)稱為OSI。
OSI的七層協(xié)議體系結(jié)構(gòu)的概念分明,理論也較完整,但它既復(fù)雜又不實(shí)用,TCP/IP體系結(jié)構(gòu)那么不同,但它現(xiàn)在卻得到了非常廣泛的應(yīng)用。TCP/IP是一個(gè)四層體系結(jié)構(gòu),它包含應(yīng)用層,運(yùn)輸層,網(wǎng)際層和網(wǎng)絡(luò)接口層〔用網(wǎng)際層這個(gè)名字是強(qiáng)調(diào)這一層是為了解決不同網(wǎng)絡(luò)的互連問(wèn)題〕,不過(guò)從實(shí)質(zhì)上講,TCP/IP只有最上面的三層,因?yàn)樽钕旅娴木W(wǎng)絡(luò)接口層并沒(méi)有什么具體內(nèi)容,因此在學(xué)習(xí)計(jì)算機(jī)網(wǎng)絡(luò)的原理時(shí)往往采用折中的方法,即綜合OSI和TCP/IP的優(yōu)點(diǎn),采用一種只有五層協(xié)議的體系結(jié)構(gòu),這樣既簡(jiǎn)潔又能將概念闡述分明,有時(shí)為了方便,也可把最底下兩層稱為網(wǎng)絡(luò)接口層。
四層協(xié)議,五層協(xié)議和七層協(xié)議的關(guān)系如下:
TCP/IP是一個(gè)四層的體系結(jié)構(gòu),主要包括:應(yīng)用層、運(yùn)輸層、網(wǎng)際層和網(wǎng)絡(luò)接口層。
五層協(xié)議的體系結(jié)構(gòu)主要包括:應(yīng)用層、運(yùn)輸層、網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層和物理層。
OSI七層協(xié)議模型主要包括是:應(yīng)用層〔Application〕、表示層〔Presentation〕、會(huì)話層〔Session〕、運(yùn)輸層〔Transport〕、網(wǎng)絡(luò)層〔Network〕、數(shù)據(jù)鏈路層〔DataLink〕、物理層〔Physical〕。
注:五層協(xié)議的體系結(jié)構(gòu)只是為了介紹網(wǎng)絡(luò)原理而設(shè)計(jì)的,實(shí)際應(yīng)用還是TCP/IP四層體系結(jié)構(gòu)。
@$TCP的三次握手四次揮手的過(guò)程
TCP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,它會(huì)處理IP層或下列的層的丟包、重復(fù)以及錯(cuò)誤問(wèn)題。在發(fā)送數(shù)據(jù)前,通信雙方必須在彼此間建立一條連接。所謂的“連接〞,其實(shí)是客戶端和效勞端保留的一份關(guān)于對(duì)方的信息,如ip地址、端口號(hào)等,這些信息放在TCP頭部
一個(gè)TCP連接通常分為三個(gè)階段:連接、數(shù)據(jù)傳輸、退出〔關(guān)閉〕。通過(guò)三次握手建立一個(gè)連接,通過(guò)四次揮手來(lái)關(guān)閉一個(gè)連接。當(dāng)一個(gè)連接被建立或被終止時(shí),交換的報(bào)文段只包含TCP頭部,而沒(méi)有數(shù)據(jù)。
TCP報(bào)文的頭部結(jié)構(gòu)
在了解TCP連接之前先來(lái)了解一下TCP報(bào)文的頭部結(jié)構(gòu)。
上圖中有幾個(gè)字段需要重點(diǎn)介紹下:
〔1〕序號(hào):seq序號(hào),占32位,用來(lái)標(biāo)識(shí)從TCP源端向目的端發(fā)送的字節(jié)流,發(fā)起方發(fā)送數(shù)據(jù)時(shí)對(duì)此進(jìn)行標(biāo)記。
〔2〕確認(rèn)序號(hào):ack序號(hào),占32位,只有ACK標(biāo)志位為1時(shí),確認(rèn)序號(hào)字段才有效,ack=seq+1。
〔3〕標(biāo)志位:共6個(gè),即URG、ACK、PSH、RST、SYN、FIN等,具體含義如下:
ACK:確認(rèn)序號(hào)有效。
FIN:釋放一個(gè)連接。
PSH:接收方應(yīng)該盡快將這個(gè)報(bào)文交給應(yīng)用層。
RST:重置連接。
SYN:發(fā)起一個(gè)新連接。
URG:緊急指針〔urgentpointer〕有效。
需要注意的是:
不要將確認(rèn)序號(hào)ack與標(biāo)志位中的ACK搞混了。
確認(rèn)方ack=發(fā)起方seq+1,兩端配對(duì)。
三次握手
三次握手的本質(zhì)是確認(rèn)通信雙方收發(fā)數(shù)據(jù)的能力
首先,我讓信使運(yùn)輸一份信件給對(duì)方,對(duì)方收到了,則他就知道了我的發(fā)件能力和他的收件能力是可以的。
于是他給我回信,我假設(shè)收到了,我便知我的發(fā)件能力和他的收件能力是可以的,并且他的發(fā)件能力和我的收件能力是可以。
然而此時(shí)他還不知道他的發(fā)件能力和我的收件能力到底可不可以,于是我最后反應(yīng)一次,他假設(shè)收到了,他便分明了他的發(fā)件能力和我的收件能力是可以的。
這就是三次握手,這樣說(shuō),你理解了嗎?
第一次握手:客戶端要向效勞端發(fā)起連接請(qǐng)求,首先客戶端隨機(jī)生成一個(gè)起始序列號(hào)ISN(比方是100),那客戶端向效勞端發(fā)送的報(bào)文段包含SYN標(biāo)志位(也就是SYN=1),序列號(hào)seq=100。
第二次握手:效勞端收到客戶端發(fā)過(guò)來(lái)的報(bào)文后,發(fā)現(xiàn)SYN=1,知道這是一個(gè)連接請(qǐng)求,于是將客戶端的起始序列號(hào)100存起來(lái),并且隨機(jī)生成一個(gè)效勞端的起始序列號(hào)(比方是300)。然后給客戶端回復(fù)一段報(bào)文,回復(fù)報(bào)文包含SYN和ACK標(biāo)志(也就是SYN=1,ACK=1)、序列號(hào)seq=300、確認(rèn)號(hào)ack=101(客戶端發(fā)過(guò)來(lái)的序列號(hào)+1)。
第三次握手:客戶端收到效勞端的回復(fù)后發(fā)現(xiàn)ACK=1并且ack=101,于是知道效勞端已經(jīng)收到了序列號(hào)為100的那段報(bào)文;同時(shí)發(fā)現(xiàn)SYN=1,知道了效勞端同意了這次連接,于是就將效勞端的序列號(hào)300給存下來(lái)。然后客戶端再回復(fù)一段報(bào)文給效勞端,報(bào)文包含ACK標(biāo)志位(ACK=1)、ack=301(效勞端序列號(hào)+1)、seq=101(第一次握手時(shí)發(fā)送報(bào)文是占據(jù)一個(gè)序列號(hào)的,所以這次seq就從101開(kāi)始,需要注意的是不攜帶數(shù)據(jù)的ACK報(bào)文是不占據(jù)序列號(hào)的,所以后面第一次正式發(fā)送數(shù)據(jù)時(shí)seq還是101)。當(dāng)效勞端收到報(bào)文后發(fā)現(xiàn)ACK=1并且ack=301,就知道客戶端收到序列號(hào)為300的報(bào)文了,就這樣客戶端和效勞端通過(guò)TCP建立了連接。
四次揮手
四次揮手的目的是關(guān)閉一個(gè)連接
比方客戶端初始化的序列號(hào)ISA=100,效勞端初始化的序列號(hào)ISA=300。TCP連接成功后客戶端總共發(fā)送了1000個(gè)字節(jié)的數(shù)據(jù),效勞端在客戶端發(fā)FIN報(bào)文前總共回復(fù)了2000個(gè)字節(jié)的數(shù)據(jù)。
第一次揮手:當(dāng)客戶端的數(shù)據(jù)都傳輸完成后,客戶端向效勞端發(fā)出連接釋放報(bào)文(當(dāng)然數(shù)據(jù)沒(méi)發(fā)完時(shí)也可以發(fā)送連接釋放報(bào)文并停止發(fā)送數(shù)據(jù)),釋放連接報(bào)文包含F(xiàn)IN標(biāo)志位(FIN=1)、序列號(hào)seq=1101(100+1+1000,其中的1是建立連接時(shí)占的一個(gè)序列號(hào))。需要注意的是客戶端發(fā)出FIN報(bào)文段后只是不能發(fā)數(shù)據(jù)了,但是還可以正常收數(shù)據(jù);另外FIN報(bào)文段即使不攜帶數(shù)據(jù)也要占據(jù)一個(gè)序列號(hào)。
第二次揮手:效勞端收到客戶端發(fā)的FIN報(bào)文后給客戶端回復(fù)確認(rèn)報(bào)文,確認(rèn)報(bào)文包含ACK標(biāo)志位(ACK=1)、確認(rèn)號(hào)ack=1102(客戶端FIN報(bào)文序列號(hào)1101+1)、序列號(hào)seq=2300(300+2000)。此時(shí)效勞端處于關(guān)閉等待狀態(tài),而不是立馬給客戶端發(fā)FIN報(bào)文,這個(gè)狀態(tài)還要持續(xù)一段時(shí)間,因?yàn)樾诙丝赡苓€有數(shù)據(jù)沒(méi)發(fā)完。
第三次揮手:效勞端將最后數(shù)據(jù)(比方50個(gè)字節(jié))發(fā)送完畢后就向客戶端發(fā)出連接釋放報(bào)文,報(bào)文包含F(xiàn)IN和ACK標(biāo)志位(FIN=1,ACK=1)、確認(rèn)號(hào)和第二次揮手一樣ack=1102、序列號(hào)seq=2350(2300+50)。
第四次揮手:客戶端收到效勞端發(fā)的FIN報(bào)文后,向效勞端發(fā)出確認(rèn)報(bào)文,確認(rèn)報(bào)文包含ACK標(biāo)志位(ACK=1)、確認(rèn)號(hào)ack=2351、序列號(hào)seq=1102。注意客戶端發(fā)出確認(rèn)報(bào)文后不是立馬釋放TCP連接,而是要經(jīng)過(guò)2MSL(最長(zhǎng)報(bào)文段壽命的2倍時(shí)長(zhǎng))后才釋放TCP連接。而效勞端一旦收到客戶端發(fā)出確實(shí)認(rèn)報(bào)文就會(huì)立馬釋放TCP連接,所以效勞端結(jié)束TCP連接的時(shí)間要比客戶端早一些。
為什么TCP連接的時(shí)候是3次?2次不可以嗎?
因?yàn)樾枰紤]連接時(shí)丟包的問(wèn)題,如果只握手2次,第二次握手時(shí)如果效勞端發(fā)給客戶端確實(shí)認(rèn)報(bào)文段喪失,此時(shí)效勞端已經(jīng)準(zhǔn)備好了收發(fā)數(shù)(可以理解效勞端已經(jīng)連接成功)據(jù),而客戶端一直沒(méi)收到效勞端確實(shí)認(rèn)報(bào)文,所以客戶端就不知道效勞端是否已經(jīng)準(zhǔn)備好了(可以理解為客戶端未連接成功),這種情況下客戶端不會(huì)給效勞端發(fā)數(shù)據(jù),也會(huì)忽略效勞端發(fā)過(guò)來(lái)的數(shù)據(jù)。
如果是三次握手,即便發(fā)生丟包也不會(huì)有問(wèn)題,比方如果第三次握手客戶端發(fā)確實(shí)認(rèn)ack報(bào)文喪失,效勞端在一段時(shí)間內(nèi)沒(méi)有收到確認(rèn)ack報(bào)文的話就會(huì)重新進(jìn)行第二次握手,也就是效勞端會(huì)重發(fā)SYN報(bào)文段,客戶端收到重發(fā)的報(bào)文段后會(huì)再次給效勞端發(fā)送確認(rèn)ack報(bào)文。
為什么TCP連接的時(shí)候是3次,關(guān)閉的時(shí)候卻是4次?
因?yàn)橹挥性诳蛻舳撕托诙硕紱](méi)有數(shù)據(jù)要發(fā)送的時(shí)候才能斷開(kāi)TCP。而客戶端發(fā)出FIN報(bào)文時(shí)只能保證客戶端沒(méi)有數(shù)據(jù)發(fā)了,效勞端還有沒(méi)有數(shù)據(jù)發(fā)客戶端是不知道的。而效勞端收到客戶端的FIN報(bào)文后只能先回復(fù)客戶端一個(gè)確認(rèn)報(bào)文來(lái)告訴客戶端我效勞端已經(jīng)收到你的FIN報(bào)文了,但我效勞端還有一些數(shù)據(jù)沒(méi)發(fā)完,等這些數(shù)據(jù)發(fā)完了,效勞端才能給客戶端發(fā)FIN報(bào)文(所以不能一次性將確認(rèn)報(bào)文和FIN報(bào)文發(fā)給客戶端,就是這里多出來(lái)了一次)。
為什么客戶端發(fā)出第四次揮手確實(shí)認(rèn)報(bào)文后要等2MSL的時(shí)間才能釋放TCP連接?
要考慮丟包的問(wèn)題,如果第四次揮手的報(bào)文喪失,效勞端沒(méi)收到確認(rèn)ack報(bào)文就會(huì)重發(fā)第三次揮手的報(bào)文,這樣報(bào)文一去一回最長(zhǎng)時(shí)間就是2MSL,所以需要等這么長(zhǎng)時(shí)間來(lái)確認(rèn)效勞端的確已經(jīng)收到了。
@$滑動(dòng)窗口協(xié)議
為了最大效率的利用網(wǎng)絡(luò)資源,增加網(wǎng)絡(luò)的吞吐量,便產(chǎn)生了“滑動(dòng)窗口〞這種協(xié)議?;瑒?dòng)窗口機(jī)制是TCP協(xié)議中用來(lái)控制發(fā)送數(shù)據(jù)包速率的,發(fā)送方每次只能發(fā)送滑動(dòng)窗口內(nèi)部的數(shù)據(jù)包,同時(shí)解決了丟包,出錯(cuò),亂序等一些情況。
問(wèn)題一:如何保證次序?
提出問(wèn)題:在我們滑動(dòng)窗口協(xié)議之前,我們?nèi)绾蝸?lái)保證發(fā)送方與接收方之間,每個(gè)包都能被收到。并且是按次序的呢?
發(fā)送方發(fā)送一個(gè)包1,這時(shí)候接收方確認(rèn)包1。發(fā)送包2,確認(rèn)包2。就這樣一直下去,直到把數(shù)據(jù)完全發(fā)送完畢,這樣就結(jié)束了。則就解決了丟包,出錯(cuò),亂序等一些情況!同時(shí)也存在一些問(wèn)題。問(wèn)題:吞吐量非常的低。我們發(fā)完包1,一定要等確認(rèn)包1。我們才能發(fā)送第二個(gè)包。
問(wèn)題二:如何提高吞吐量?
提出問(wèn)題:則我們就不能先連發(fā)幾個(gè)包等他一起確認(rèn)嗎?這樣的話,我們的速度會(huì)不會(huì)更快,吞吐量更高些呢?
如圖,這個(gè)就是我們把兩個(gè)包一起發(fā)送,然后一起確認(rèn)??梢钥闯鑫覀兏牧嫉挠?jì)劃比之前的好很多,所花的時(shí)間只是一個(gè)來(lái)回的時(shí)間。接下來(lái),我們還有一個(gè)問(wèn)題:改善了吞吐量的問(wèn)題
問(wèn)題三:如何實(shí)現(xiàn)最優(yōu)解?
問(wèn)題:我們每次需要發(fā)多少個(gè)包過(guò)去呢?發(fā)送多少包是最優(yōu)解呢?
我們能不能把第一個(gè)和第二個(gè)包發(fā)過(guò)去后,收到第一個(gè)確認(rèn)包就把第三個(gè)包發(fā)過(guò)去呢?而不是去等到第二個(gè)包確實(shí)認(rèn)包才去發(fā)第三個(gè)包。這樣就很自然的產(chǎn)生了我們"滑動(dòng)窗口"的實(shí)現(xiàn)。
每收到一個(gè)新確實(shí)認(rèn)(ack),滑動(dòng)窗口的位置就向右移動(dòng)一格。
在圖中,我們可看出灰色1號(hào)2號(hào)3號(hào)包已經(jīng)發(fā)送完畢,并且已經(jīng)收到Ack。這些包就已經(jīng)是過(guò)去式。4、5、6、7號(hào)包是黃色的,表示已經(jīng)發(fā)送了。但是并沒(méi)有收到對(duì)方的Ack,所以也不知道接收方有沒(méi)有收到。8、9、10號(hào)包是綠色的。是我們還沒(méi)有發(fā)送的。這些綠色也就是我們接下來(lái)馬上要發(fā)送的包。后面的11-16還沒(méi)有被讀進(jìn)內(nèi)存。
正常情況
可以看到4號(hào)包對(duì)方已經(jīng)被接收到,所以被涂成了灰色。“窗口〞就往右移一格,這里只要保證“窗口〞是7格的。我們就把11號(hào)包讀進(jìn)了我們的緩存。進(jìn)入了“待發(fā)送〞的狀態(tài)。8、9號(hào)包已經(jīng)變成了黃色,表示已經(jīng)發(fā)送出去了。接下來(lái)的操作就是一樣的了,確認(rèn)包后,窗口往后移,繼續(xù)將未發(fā)送的包讀進(jìn)緩存,把“待發(fā)送“狀態(tài)的包變?yōu)楱曇寻l(fā)送“。
丟包情況
有可能我們包發(fā)過(guò)去,對(duì)方的Ack丟了,也有可能我們的包并沒(méi)有發(fā)送過(guò)去。從發(fā)送方角度看就是我們沒(méi)有收到Ack。
發(fā)生的情況:一直在等Ack。如果一直等不到的話,我們也會(huì)把讀進(jìn)緩存的待發(fā)送的包也一起發(fā)過(guò)去。但是,這個(gè)時(shí)候我們的窗口已經(jīng)發(fā)滿了。所以并不能把12號(hào)包讀進(jìn)來(lái),而是始終在等待5號(hào)包的Ack。
如果我們這個(gè)Ack始終不來(lái)怎么辦呢?
超時(shí)重發(fā)
這時(shí)候我們有個(gè)解決辦法:超時(shí)重發(fā)這里有一點(diǎn)要表明:這個(gè)Ack是要按順序的。必須要等到5的Ack收到,才會(huì)把6-11的Ack發(fā)送過(guò)去。這樣就保證了滑動(dòng)窗口的一個(gè)順序。
這時(shí)候可以看出5號(hào)包已經(jīng)接受到Ack,后面的6、7、8號(hào)包也已經(jīng)發(fā)送過(guò)去已Ack。窗口便繼續(xù)向后移動(dòng)。
@$DNS解析過(guò)程
DNS〔DomainNameSystem〕:因特網(wǎng)使用的域名系統(tǒng),本質(zhì)是一個(gè)分布式數(shù)據(jù)庫(kù),用于解決域名和IP地址的映射關(guān)系。
DNS解析:互聯(lián)網(wǎng)都是通過(guò)URL來(lái)請(qǐng)求資源的,而URL中的域名需要解析成IP地址才能與遠(yuǎn)程主機(jī)建立連接,將域名解析成IP地址就屬于DNS解析的工作范疇。
域名結(jié)構(gòu)
從技術(shù)角度來(lái)看,域名是在Internet上用于解決IP地址的一種辦法。一個(gè)完整的域名由2個(gè)或2個(gè)以上的局部組成,各局部之間用英文的句號(hào)“.〞來(lái)分隔,最后一個(gè)“.〞的右邊局部稱為頂級(jí)域名(TLD,也稱為一級(jí)域名),最后一個(gè)“.〞的左邊局部稱為二級(jí)域名(SLD),二級(jí)域名的左邊局部稱為三級(jí)域名,以此類推,每一級(jí)的域名控制它下一級(jí)域名的分配。
如域名mail.cctv,其中:com為頂級(jí)域名〔top-level-domain,TLD〕,cctv為二級(jí)域名,mail為三級(jí)域名
DNS解析過(guò)程
瀏覽器會(huì)檢查緩存中有沒(méi)有這域名對(duì)應(yīng)的解析過(guò)的IP地址,如果緩存中有,這個(gè)解析過(guò)程就將結(jié)束。
如果過(guò)程1中瀏覽器緩存中沒(méi)有域名對(duì)應(yīng)的ip,那么從操作系統(tǒng)本身去做域名解析,我們?cè)趙indows中的host文件可以設(shè)置特定域名映射到特定ip。C:\Windows\System32\drivers\etc\hosts
然后在終端中pingwww.baidu,如圖所示所示:
向本地域名解析效勞器〔LDNS〕發(fā)起域名解析請(qǐng)求
上述步驟的1、2都是在本機(jī)中完成的域名解析,如果經(jīng)過(guò)1、2步驟都沒(méi)有完成域名的解析,那么需要向LDNS發(fā)起域名解析,對(duì)于LDNS,Window中可以通過(guò)ipconfig/all來(lái)查詢,如下所示:
LDNS一般都緩存了大局部的域名解析結(jié)果,當(dāng)然緩存時(shí)間也受域名失效的時(shí)間控制,大局部的解析工作到這里就差不多結(jié)束了,LDNS負(fù)責(zé)了大局部的解析工作。
向根域名解析效勞器〔RDNS〕發(fā)起域名解析的請(qǐng)求
當(dāng)步驟3中沒(méi)有完成域名的解析,那么需要向RDNS發(fā)起域名解析的請(qǐng)求
根域名效勞器返回通用頂級(jí)域名解析效勞器〔gTDL〕地址
LDNS向根域名效勞器發(fā)起請(qǐng)求,根域名效勞器返回的是所查詢的通用頂級(jí)域名〔Generictop-level-domain,gTLD〕地址,常見(jiàn)的通用頂級(jí)域名有、.org、.edu。
本地域名效勞器向gTLD發(fā)起解析域名請(qǐng)求
gTLD效勞器接收請(qǐng)求并返回注冊(cè)的域名效勞器〔NameServer效勞器,即名稱效勞器〕
當(dāng)gTLD效勞器接收到本地域名效勞器發(fā)起的請(qǐng)求后,并根據(jù)需要解析的域名,找到該域名對(duì)應(yīng)的NameServer效勞器,通常情況下,這個(gè)NameServer效勞器就是你注冊(cè)的域名效勞器,則你注冊(cè)的域名的效勞上的效勞器將承當(dāng)起域名解析的任務(wù)。
本地域名效勞器向NameServer效勞器發(fā)起域名解析請(qǐng)求
NameServer效勞器會(huì)查詢存儲(chǔ)的域名和IP的映射關(guān)系表,然后返回該域名對(duì)應(yīng)的ip和TTL給本地域名效勞器,本地域名效勞器進(jìn)行緩存這個(gè)域名和ip的對(duì)應(yīng)關(guān)系,緩存時(shí)間由TTL決定。
本地域名效勞器返回查詢域名對(duì)應(yīng)的ip給用戶〔瀏覽器〕,瀏覽器進(jìn)行緩存,緩存時(shí)間由TTL決定。
經(jīng)過(guò)以上的10個(gè)步驟,就可以拿到真正的ip了,然后通過(guò)ip去對(duì)應(yīng)的效勞器上請(qǐng)求資源。
@$CDN原理,CDN加速過(guò)程
CDN內(nèi)容分發(fā)網(wǎng)絡(luò),全稱為ContentDeliveryNetwork,通過(guò)將網(wǎng)絡(luò)內(nèi)容發(fā)布到最靠近用戶的『邊緣節(jié)點(diǎn)』,使不同地區(qū)的用戶在訪問(wèn)相同頁(yè)面、或視頻時(shí)就可以就近獲取。
CDN本質(zhì)是一種分布式緩存系統(tǒng),無(wú)需考慮數(shù)據(jù)持久化,如果緩存效勞器出現(xiàn)問(wèn)題,在緩存集群中標(biāo)記為刪除即可。
CDN中實(shí)現(xiàn)原理:給源站域名添加CNAME別名,別名為加速節(jié)點(diǎn)的域名。當(dāng)用戶向源站發(fā)起請(qǐng)求時(shí),dns效勞器解析源站域名時(shí)會(huì)發(fā)現(xiàn)有CNAME記錄,這時(shí)dns效勞器會(huì)向CNAME域名發(fā)起請(qǐng)求,請(qǐng)求會(huì)被調(diào)度至加速節(jié)點(diǎn)的域名。
CDN的優(yōu)點(diǎn)
根據(jù)用戶與業(yè)務(wù)效勞器的距離,自動(dòng)選擇就近的cache效勞器
鏡像效勞,打消運(yùn)營(yíng)商之間互聯(lián)的瓶頸影響,保證不同網(wǎng)絡(luò)的用戶都能得到良好的訪問(wèn)質(zhì)量
帶寬優(yōu)化,分擔(dān)網(wǎng)絡(luò)流量,減輕壓力
域名與ip的對(duì)應(yīng)關(guān)系,被稱為記錄(record),可分為各種類型
A記錄:Address,域名指向的IP地址,A記錄允許將多個(gè)域名解析到一個(gè)IP地址,但不允許將一個(gè)域名解析到多個(gè)IP上。
NS記錄:NameServer,指定了特定的DNS效勞器去解析。
MX記錄:MaileXchange,接受電子郵件的效勞器地址
CNAME記錄:CanonicalName,別名解析,可以將指定的域名解析到其他域名上
CDN的過(guò)程
使用CDN的辦法很簡(jiǎn)單,只需要修改自己的DNS解析,設(shè)置一個(gè)CNAME指向CDN效勞商即可。
用戶訪問(wèn)未使用CDN緩存資源的過(guò)程
瀏覽器通過(guò)DNS解析,以得到此域名對(duì)應(yīng)的IP地址;
瀏覽器使用所得到的IP地址,向域名的效勞主機(jī)發(fā)出數(shù)據(jù)訪問(wèn)請(qǐng)求;
效勞器向?yàn)g覽器返回響應(yīng)數(shù)據(jù)
使用CDN后
若您的加速域名為www.a,接入CDN網(wǎng)絡(luò),開(kāi)始使用加速效勞后,當(dāng)終端用戶〔北京〕發(fā)起HTTP請(qǐng)求時(shí),處理流程如圖所示所示。
當(dāng)終端用戶〔北京〕向www.a下的指定資源發(fā)起請(qǐng)求時(shí),首先向LDNS〔本地DNS〕發(fā)起域名解析請(qǐng)求。
LDNS檢查緩存中是否有www.a的IP地址記錄。如果有,那么直接返回給終端用戶;如果沒(méi)有,那么向授權(quán)DNS查詢。
當(dāng)授權(quán)DNS解析www.a時(shí),返回域名CNAMEwww.a.tbcdn對(duì)應(yīng)IP地址。
域名解析請(qǐng)求發(fā)送至阿里云DNS調(diào)度系統(tǒng),并為請(qǐng)求分配最正確節(jié)點(diǎn)IP地址。
LDNS獲取DNS返回的解析IP地址。
用戶獲取解析IP地址。
用戶向獲取的IP地址發(fā)起對(duì)該資源的訪問(wèn)請(qǐng)求。
如果該IP地址對(duì)應(yīng)的節(jié)點(diǎn)已緩存該資源,那么會(huì)將數(shù)據(jù)直接返回給用戶,示例,圖中步驟7和8,請(qǐng)求結(jié)束。
如果該IP地址對(duì)應(yīng)的節(jié)點(diǎn)未緩存該資源,那么節(jié)點(diǎn)向源站發(fā)起對(duì)該資源的請(qǐng)求。獲取資源后,結(jié)合用戶自定義配置的緩存策略,將資源緩存至節(jié)點(diǎn),示例,圖中的北京節(jié)點(diǎn),并返回給用戶,請(qǐng)求結(jié)束。
GET和POST區(qū)別
說(shuō)道GET和POST,就不得不提HTTP協(xié)議,因?yàn)闉g覽器和效勞器的交互是通過(guò)HTTP協(xié)議執(zhí)行的,而GET和POST也是HTTP協(xié)議中的兩種辦法。
HTTP全稱為HyperTextTransferProtocol,中文翻譯為超文本傳輸協(xié)議,目的是保證瀏覽器與效勞器之間的通信。HTTP的工作方式是客戶端與效勞端之間的請(qǐng)求-應(yīng)答協(xié)議。
HTTP協(xié)議中定義了瀏覽器和效勞器進(jìn)行交互的不同辦法,根本辦法有4種,分別是GET,POST,PUT,DELETE。這四種辦法可以理解為,對(duì)效勞器資源的查,改,增,刪。
GET:從效勞器上獲取數(shù)據(jù),也就是所謂的查,僅僅是獲取效勞器資源,不進(jìn)行修改。
POST:向效勞器提交數(shù)據(jù),這就波及到了數(shù)據(jù)的更新,也就是更改效勞器的數(shù)據(jù)。
PUT:英文含義是放置,也就是向效勞器新添加數(shù)據(jù),就是所謂的增。
DELETE:從字面意思也能看出,這種方式就是刪除效勞器數(shù)據(jù)的過(guò)程。
GET和POST區(qū)別
Get是不平安的,因?yàn)樵趥鬏斶^(guò)程,數(shù)據(jù)被放在請(qǐng)求的URL中;Post的所有操作對(duì)用戶來(lái)說(shuō)都是不可見(jiàn)的。但是這種做法也不是絕對(duì)的,大局部人的做法也是按照上面的說(shuō)法來(lái)的,但是也可以在get請(qǐng)求加上requestbody,給post請(qǐng)求帶上URL參數(shù)。
Get請(qǐng)求提交的url中的數(shù)據(jù)最多只能是2048字節(jié),這個(gè)限制是瀏覽器或者效勞器給添加的,http協(xié)議并沒(méi)有對(duì)url長(zhǎng)度進(jìn)行限制,目的是為了保證效勞器和瀏覽器能夠正常運(yùn)行,避免有人歹意發(fā)送請(qǐng)求。Post請(qǐng)求那么沒(méi)有大小限制。
Get限制Form表單的數(shù)據(jù)集的值必須為ASCII字符;而Post支持整個(gè)ISO10646字符集。
Get執(zhí)行效率比Post快。Get是form提交的默認(rèn)辦法。
GET產(chǎn)生一個(gè)TCP數(shù)據(jù)包;POST產(chǎn)生兩個(gè)TCP數(shù)據(jù)包。
對(duì)于GET方式的請(qǐng)求,瀏覽器會(huì)把httpheader和data一并發(fā)送出去,效勞器響應(yīng)200〔返回?cái)?shù)據(jù)〕;
而對(duì)于POST,瀏覽器先發(fā)送header,效勞器響應(yīng)100continue,瀏覽器再發(fā)送data,效勞器響應(yīng)200ok〔返回?cái)?shù)據(jù)〕。
Get Post
平安性 Get是不平安的,因?yàn)樵趥鬏斶^(guò)程,數(shù)據(jù)被放在請(qǐng)求的URL中 Post的所有操作對(duì)用戶來(lái)說(shuō)都是不可見(jiàn)的,相對(duì)平安
url數(shù)據(jù)大小 Get請(qǐng)求提交的url中的數(shù)據(jù)受瀏覽器和效勞器的限制,避免有人歹意發(fā)送請(qǐng)求 Post請(qǐng)求url數(shù)據(jù)沒(méi)有大小限制
表單字符集 Get限制Form表單的數(shù)據(jù)集的值必須為ASCII字符 Post支持整個(gè)ISO10646字符集
TCP數(shù)據(jù)包數(shù)量 GET產(chǎn)生一個(gè)TCP數(shù)據(jù)包 POST產(chǎn)生兩個(gè)TCP數(shù)據(jù)包
執(zhí)行效率 Get執(zhí)行效率比Post快 Post執(zhí)行效率比Get慢
@$Session、Cookie和Token的主要區(qū)別
HTTP協(xié)議本身是無(wú)狀態(tài)的。什么是無(wú)狀態(tài)呢,即效勞器無(wú)法判斷用戶身份。
什么是cookie
cookie是由Web效勞器保留在用戶瀏覽器上的小文件〔key-value格式〕,包含用戶相關(guān)的信息。客戶端向效勞器發(fā)起請(qǐng)求,如果效勞器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個(gè)Cookie。客戶端瀏覽器會(huì)把Cookie保留起來(lái)。當(dāng)瀏覽器再請(qǐng)求該網(wǎng)站時(shí),瀏覽器把請(qǐng)求的網(wǎng)址連同該Cookie一同提交給效勞器。效勞器檢查該Cookie,以此來(lái)識(shí)別用戶身份。
什么是session
session是依賴Cookie實(shí)現(xiàn)的。session是效勞器端對(duì)象
session是瀏覽器和效勞器會(huì)話過(guò)程中,效勞器分配的一塊儲(chǔ)存空間。效勞器默認(rèn)為瀏覽器在cookie中設(shè)置sessionid,瀏覽器在向效勞器請(qǐng)求過(guò)程中傳輸cookie包含sessionid,效勞器根據(jù)sessionid獲取出會(huì)話中存儲(chǔ)的信息,然后確定會(huì)話的身份信息。
cookie與session區(qū)別
存儲(chǔ)位置與平安性:cookie數(shù)據(jù)寄存在客戶端上,平安性較差,session數(shù)據(jù)放在效勞器上,平安性相對(duì)更高;
存儲(chǔ)空間:?jiǎn)蝹€(gè)cookie保留的數(shù)據(jù)不能超過(guò)4K,很多瀏覽器都限制一個(gè)站點(diǎn)最多保留20個(gè)cookie,session無(wú)此限制
占用效勞器資源:session一定時(shí)間內(nèi)保留在效勞器上,當(dāng)訪問(wèn)增多,占用效勞器性能,考慮到效勞器性能方面,應(yīng)當(dāng)使用cookie。
什么是Token
Token的引入:Token是在客戶端頻繁向效勞端請(qǐng)求數(shù)據(jù),效勞端頻繁的去數(shù)據(jù)庫(kù)查詢用戶名和密碼并進(jìn)行比照,判斷用戶名和密碼正確與否,并作出相應(yīng)提示,在這樣的背景下,Token便應(yīng)運(yùn)而生。
Token的定義:Token是效勞端生成的一串字符串,以作客戶端進(jìn)行請(qǐng)求的一個(gè)令牌,當(dāng)?shù)谝淮蔚卿浐?,效勞器生成一個(gè)Token便將此Token返回給客戶端,以后客戶端只需帶上這個(gè)Token前來(lái)請(qǐng)求數(shù)據(jù)即可,無(wú)需再次帶上用戶名和密碼。
使用Token的目的:Token的目的是為了減輕效勞器的壓力,減少頻繁的查詢數(shù)據(jù)庫(kù),使效勞器更加健壯。
session與token區(qū)別
session機(jī)制存在效勞器壓力增大,CSRF跨站偽造請(qǐng)求攻擊,擴(kuò)展性不強(qiáng)等問(wèn)題;
session存儲(chǔ)在效勞器端,token存儲(chǔ)在客戶端
token提供認(rèn)證和授權(quán)功能,作為身份認(rèn)證,token平安性比session好;
session這種會(huì)話存儲(chǔ)方式方式只適用于客戶端代碼和效勞端代碼運(yùn)行在同一臺(tái)效勞器上,token適用于工程級(jí)的前后端別離〔前后端代碼運(yùn)行在不同的效勞器下〕
Servlet接口中有哪些辦法及Servlet生命周期探秘
在JavaWeb程序中,Servlet主要負(fù)責(zé)接收用戶請(qǐng)求HttpServletRequest,在doGet(),doPost()中做相應(yīng)的處理,并將回應(yīng)HttpServletResponse反應(yīng)給用戶。Servlet可以設(shè)置初始化參數(shù),供Servlet內(nèi)部使用。
Servlet接口定義了5個(gè)辦法,其中前三個(gè)辦法與Servlet生命周期相關(guān):
voidinit(ServletConfigconfig)throwsServletException
voidservice(ServletRequestreq,ServletResponseresp)throwsServletException,java.io.IOException
voiddestory()
java.lang.StringgetServletInfo()
ServletConfiggetServletConfig()
生命周期:
Web容器加載Ser
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度家庭自用房屋贈(zèng)與合同模板3篇
- 2025年度音樂(lè)節(jié)舞臺(tái)搭建、燈光音響及特效服務(wù)合同3篇
- 2025年度房屋裝修與家具配置一體化采購(gòu)合同3篇
- 二零二五年度環(huán)保拆解與資源化利用合同3篇
- 二零二五年度能源項(xiàng)目委托收購(gòu)合同模板
- 二零二五年度2025房產(chǎn)轉(zhuǎn)讓及社區(qū)健身設(shè)施建設(shè)合同3篇
- 大同中學(xué)自招數(shù)學(xué)試卷
- 2024民用航空貨運(yùn)代理貨物安全運(yùn)輸合同范本2篇
- 初二電白區(qū)期末數(shù)學(xué)試卷
- 核化工與核燃料工程專業(yè)就業(yè)能力展示
- 人教版PEP英語(yǔ)三年級(jí)上冊(cè) Unit 5 Let's eat!Part A Lets learn 教案
- 公職人員挪用公款檢討書(shū)
- 中級(jí)消防設(shè)施操作員(維保)實(shí)操技能考試題庫(kù)(濃縮500題)
- NB-T32042-2018光伏發(fā)電工程建設(shè)監(jiān)理規(guī)范
- 高級(jí)市場(chǎng)分析師勞動(dòng)合同范本
- JT-T-1211.1-2018公路工程水泥混凝土用快速修補(bǔ)材料第1部分:水泥基修補(bǔ)材料
- 垃圾焚燒行業(yè)經(jīng)營(yíng)分析報(bào)告
- JBT 14589-2024 敷膠雙螺桿泵(正式版)
- 供應(yīng)商交貨期協(xié)議書(shū)
- 大學(xué)生防詐騙課件
- 2024屆四川省眉山市仁壽縣中考聯(lián)考數(shù)學(xué)試卷含解析
評(píng)論
0/150
提交評(píng)論