技術問答集錦(四)

2 TCP 與 UDP

  1. 網絡層:IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議;
  2. 傳輸層:TCP協議與UDP協議;
  3. 應用層:FTP、HTTP、TELNET、SMTP、DNS等協議;

HTTP是應用層協議,其傳輸都是被包裝成TCP協議傳輸。能夠用SOCKET實現HTTP。前端

Socket是一組接口,能夠實現TCP,也能夠實現UDP。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/UDP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。java

網絡協議結構

  1. TCP --- 傳輸控制協議,提供的是面向鏈接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間創建一個TCP鏈接,以後才能傳輸數據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另外一端。 理想狀態下,TCP鏈接一旦創建,在通訊雙方中的任何一方主動關閉鏈接前,TCP 鏈接都將被一直保持下去。斷開鏈接時服務器和客戶端都可以主動發起斷開TCP鏈接的請求。ios

  2. UDP --- 用戶數據報協議,是一個無鏈接的簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據包發送出去,可是並不能保證它們能到達目的地。因爲UDP在傳輸數據包前不用在客戶和服務器之間創建一個鏈接,且沒有超時重發等機制,故而傳輸速度很快。程序員

  3. TCP鏈接的三次握手:要了解TCP,必定要知道 "三次握手,四次拜拜" 所謂的三次握手,就是發送數據前必須創建的鏈接叫三次握手,握手完了纔開始發的,這也就是面向鏈接的意思。web

  1. 第一次握手:客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
  2. 第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時本身也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
  3. 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

3 Java Thread

程序:是一段靜態代碼,它是應用軟件執行的藍本。算法

進程:是程序運行時的一個實例,對應了從代碼加載、執行的一個完整過程,此過程也對應進程產生、發展到消亡的過程。設計模式

線程:比進程更小的執行單位,一個進程在其執行過程當中,能夠產生多個執行線程,即每一個線程也有它的產生、發展到消亡的過程。是一個動態概念。瀏覽器

  1. 粒度層次不一樣,是兩個不一樣層次上的概念。進程是由操做系統來管理的,而線程則是由進程來管理。
  2. 共享資源不一樣,不一樣進程的代碼、內部數據和狀態都是徹底獨立的,而一個進程內的多線程是共享進程空間資源的,有可能互相影響。
  3. 切換效率不一樣,線程自己的數據一般只有寄存器數據,以及一個進程執行時使用的堆棧,因此線程比進程切換負擔小。

3.1 Thread生命週期及狀態模型

線程生命週期

3.2 Thread 經常使用方法

  1. Thread:

public static Thread currentThread( ):返回當前線程對象,是一個靜態的方法。緩存

public static void sleep( long millis):使當前線程進入睡眠狀態,參數設定其等待時間,不會釋放鎖,靜態方法。tomcat

public static void yield():使當前線程放棄執行,切換到其它線程,是一個靜態方法。

  1. Thread Instance:

public void start():啓動線程,JVM將調用此線程的run方法,結果是將同時運行兩個線程,當前線程和執行run方法的線程。

public void run():Thread的子類應該重寫此方法,內容應爲該線程應執行的任務。

public void stop():中止線程運行,並退出可執行狀態。 【已過期】

public void resume():將暫停的線程繼續執行。【已過期】

public void suspend():使線程暫停執行,不退出可執行態。【已過期】

public void interrupt():中斷線程。

public void join():在當前線程中加入調用join方法的線程A,直到線程A死亡才能繼續執行當前線程。

public void join(long millis):在當前線程中加入調用join方法的線程A,直到到達參數指定的毫秒數或線程A死亡才能繼續執行當前線程。

public void setPriority(int newPriority):設置線程優先級。

public void setDaemon(boolean on):設置是否爲後臺線程。若是當前運行線程均爲後臺線程則JVM中止運行。該方法必須在start()方法以前使用。

public final void checkAccess():判斷當前線程是否有權力修改調用此方法的線程。

public boolean isAlive():判斷線程是否處於執行狀態。返回值true表示處於運行狀態,false表示已中止。

  1. Object:

public void wait():在其餘線程調用此對象的notify()方法或notifyAll() 方法前,使當前線程進入等待狀態,會釋放鎖。

public void notify(): 喚醒在此對象監視器上等待的單個線程。

public void notifyAll():喚醒在此對象監視器上等待的全部線程。

3.3 main() 主線程與子線程

  1. 主線程:Java應用程序老是從主類的main()方法開始執行。當JVM加載代碼,發現main方法以後,啓動的線程稱做「主線程」,該線程負責執行main方法。
  2. 子線程:在main方法的執行中再建立的線程。

若是main方法中又建立了子線程,那麼JVM就要在主線程和子線程之間輪流切換,main方法即便執行完最後的語句,JVM也不會結束程序,JVM一直要等到程序中的全部線程都結束以後,才結束咱們的Java應用程序

3.4 Thread 線程建立兩種方法

  1. Thread類:Thread類的子類建立線程對象,子類重寫Thread類中的run()方法

    在Java程序中建立多線程的方法之一是繼承Thread類,從Thread類派生一個子類,並建立這個子類的對象,就能夠產生一個新的線程。這個子類應該重寫Thread類的run方法,在run方法中寫入須要在新線程中執行的語句段。這個子類的對象須要調用start方法來啓動,新線程等待CPU調度將自動進入run方法。當前線程將同時繼續往下執行。

    當建立子類的多個線程對象時,其成員變量和run()方法中局部變量都是互不干擾的

  2. Runnable接口:使用Thread類直接建立線程對象,但須要傳入實現Runable接口的目標對象

    在編寫複雜程序時相關的類可能已經繼承了某個基類,而Java不支持多繼承,在這種狀況下,便須要經過實現Runnable接口來生成多線程。

    使用Thread建立線程對象時,一般使用的構造方法是:Thread(Runnable target),該構造方法中的參數是一個Runnable類型的接口,所以,在建立線程對象時必須向構造方法的參數傳遞一個實現Runnable接口類的實例,該實例對象稱做所創線程的目標對象。

    當線程調用start方法後,一旦輪到它來享用CPU資源,目標對象就會自動調用接口中的run方法(接口回調)。

    對於使用同一目標對象的線程,目標對象的成員變量天然就是這些線程的共享數據單元。不一樣run()方法中的局部變量互不干擾

3.5 Thread 同步

synchronized —— 線程同步關鍵字

把須要修改數據的方法用關鍵字synchronized來修飾,用於指定須要同步的代碼段或方法,也就是監視區。

當一個線程A使用一個synchronized修飾的方法時,其餘線程想使用這個方法時就必須等待,直到線程A 使用完該方法 (除非線程A使用wait主動讓出CUP資源)。

當被synchronized限定的代碼段執行完,就釋放對象鎖(信號量)。

3.6 Thread 通訊

爲了更有效地協調不一樣線程的工做,須要在線程間創建溝通渠道,經過線程間的「對話」來解決線程間的同步問題。

java.lang.Object 類的一些方法爲線程間的通信提供了有效手段。

一個線程在使用的同步方法中時,可能根據問題的須要,必須使用wait() (掛起)方法使本線程等待,暫時讓出CPU的使用權,並容許其它線程使用這個同步方法。其它線程若是在使用這個同步方法時若是不須要等待,那麼它用完這個同步方法的同時,應當執行notify(), notifyAll()(恢復)方法通知全部的因爲使用這個同步方法而處於等待的線程結束等待

3.7 Thread 調度機制

每一個Java線程都有一個優先級,其範圍都在1和10之間。 默認狀況下,每一個線程的優先級都設置爲5

在線程A運行過程當中建立的新的線程對象B,初始狀態具備和線程A相同的優先級。可在線程建立以後的任什麼時候候,經過setPriority(int priority)方法改變其原來的優先級。

基於線程優先級的線程調度:

  1. 具備較高優先級的線程比優先級較低的線程優先執行;
  2. 對具備相同優先級的線程,Java的處理是隨機的;
  3. 底層操做系統支持的優先級可能要少於10個,這樣會形成一些混亂。所以,只能將優先級做爲一種很粗略的工具使用。最後的控制能夠經過明智地使用yield()函數來完成;

假設某線程正在運行,則只有出現如下狀況之一,纔會使其暫停運行:

  1. 一個具備更高優先級的線程變爲就緒狀態(Ready);
  2. 因爲輸入/輸出(或其餘一些緣由)、調用sleep、wait、yield方法使其發生阻塞;
  3. 對於支持時間分片的系統,時間片的時間期滿;

一般,咱們在一個線程內部插入yield()語句,這個方法會使正在運行的線程暫時放棄執行,這時具備一樣優先級的線程就有機會得到調度開始運行,但較低優先級的線程仍將被忽略不參加調度;

3.8 Thread 掛起與恢復

掛起 有時候兩個線程並非同步的,即不涉及都須要調用一個同步方法,但線程也可能須要暫時的掛起。所謂掛起一個線程就是讓線程暫時讓出CPU的使用權限,暫時中止執行,但中止執行的持續時間不肯定,所以不能使用sleep方法暫停線程。掛起一個線程需使用wait方法,即讓準備掛起的線程調用 wait 方法,主動讓出CPU的使用權限

恢復 爲了恢復該線程,其它線程在佔有CUP資源期間,讓掛起的線程的目標對象執行notifyAll()方法,使得掛起的線程繼續執行;若是線程沒有目標對象,爲了恢復該線程,其它線程在佔有CPU資源期間,讓掛起的線程調用notifyAll()方法,使掛起的線程繼續執行。

4 Java數據結構

  1. 線性表結構通常分爲三種:順序線性表、單鏈表、雙鏈表;特徵:

    1. 一個特定的線性表,應該是用來存放特定的某一個類型的元素的( 元素的「同一性」);
    2. 除第一個元素外,其餘每個元素 有且僅有一個直接前驅;除最後一個元素外,其餘每個元素 有且僅有一個直接後繼元素的「序偶性」);
    3. 元素在線性表中的「下標」 惟一地肯定該元素在表中的相對位置( 元素的「索引性」)
  2. 二叉樹是樹形結構的一個重要類型。許多實際問題抽象出來的數據結構每每是二叉樹的形式,即便是通常的樹也能簡單地轉換爲二叉樹,並且二叉樹的存儲結構及其算法都較爲簡單,所以二叉樹顯得特別重要。

    二叉樹(BinaryTree)是n(n≥0)個結點的有限集,它或者是空集(n=0),或者由一個根結點及兩棵互不相交的、分別稱做這個根的左子樹和右子樹的二叉樹組成。這個定義是遞歸的。因爲左、右子樹也是二叉樹, 所以子樹也可爲空樹。

    二叉樹遍歷:因爲被訪問的結點必是某子樹的根,因此N(Node)、L(Left subtlee)和R(Right subtree)又可解釋爲根、根的左子樹和根的右子樹。NLR、LNR和LRN分別又稱爲 先根遍歷、中根遍歷和後根遍歷

  3. 隊列是一個經常使用的數據結構,是一種 先進先出(First In First Out, FIFO) 的結構,也就是說只能在表頭進行刪除,在表尾進行添加。

  4. 棧是一種 後進先出(Last In First Out,LIFO) 的數據結構。

5 JDK命令行工具

jps : 只用於列出java的進程。

jstat :可用於觀察Java應用程序運行時信息的工具。

jinfo :可用於查看正在運行的Java應用程序的擴展參數,甚至支持在運行時修改部分參數。

jmap :生成Java應用程序的堆快照和對象的統計信息。jmap -histo 2972 > heap.log

jhat :用於分析Java應用程序的堆快照內容文件。jhat heap.log

jstack : 用於導出Java應用程序的線程堆棧。 jstack -l 2348 > jstack.log

6 靜態代理和動態代理

  1. 靜態代理:由程序員建立或工具生成代理類的源碼,再編譯代理類。所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委託類的關係在編譯期就肯定了

  2. 動態代理:動態代理類的源碼是在程序運行期間由JVM根據反射等機制動態的生成,因此不存在代理類的字節碼文件。代理類和委託類的關係是在程序運行期肯定

7 Http基礎

7.1 HTTP協議

一種通訊協議,它容許將超文本標記語言(HTML)文檔從Web服務器傳送到客戶端的瀏覽器。 一個屬於應用層的面向對象的協議,因爲其簡捷、快速的方式,適用於分佈式超媒體信息系統。

HTTP協議的主要特色以下:

  1. 支持客戶/服務器模式,基於TCP實現;
  2. 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法經常使用的有GET、POST、DELETE、PUT。每種方法規定了客戶與服務器聯繫的類型不一樣。因爲HTTP協議簡單,使得HTTP服務器的程序規模小,於是通訊速度很快;
  3. 靈活:HTTP容許傳輸任意類型的數據對象。正在 傳輸的類型由 Content-Type 加以標記
  4. 短鏈接:短鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。
  5. 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺乏狀態意味着若是後續處理須要前面的信息,則它必須重傳,這樣可能致使每次鏈接傳送的數據量增大。另外一方面,在服務器不須要先前信息時它的應答就較快。

7.2 CGI是什麼

CGI(Common Gateway Interface),通用網關接口,它是一段程序,運行在服務器上如:HTTP服務器,提供同客戶端HTML頁面的接口。利用程序的標準輸入輸出流,完成HTTP通訊。HTTP 是文本協議,每次請求的文本以標準輸入流的形式進入服務器端 CGI 程序,建立進程;而後進程的標準輸出流做爲響應

CGI程序能夠是Python腳本,PERL腳本,SHELL腳本,C或者C++程序等。 全部服務器端 HTTP 處理都是類 CGI 的原理,接受符合協議的標準輸入文本流,從標準輸出流輸出一樣符合協議的文本,也就是「請求」和「響應」

7.3 負載均衡、分佈式集羣

在負載均衡的思路下,多臺服務器爲對等方式,每臺服務器都具備同等的地位,能夠單獨對外提供服務而無須其餘服務器的輔助。經過負載分擔技術,將外部發送來的請求按必定規則分配到對稱結構中的某一臺服務器上,而接收到請求的服務器都獨立迴應客戶機的請求。

經常使用負載均衡技術:反向代理負載均衡 (如Apache+JK2+Tomcat這種組合),使用代理服務器能夠將請求轉發給內部的Web服務器,讓代理服務器將請求均勻地轉發給多臺內部Web服務器之一上,從而達到負載均衡的目的。這種代理方式與普通的代理方式有所不一樣,標準代理方式是客戶使用代理訪問多個外部Web服務器,而這種代理方式是多個客戶使用它訪問內部Web服務器,所以也被稱爲反向代理模式。

客戶系統通常採用Apache httpd做爲web服務器,即做爲Tomcat的前端處理器,根據具體狀況而定,有些狀況下是不須要Apache httpd做爲 web 服務器的,如系統展示沒有靜態頁面那就不須要Apache httpd,那時能夠直接使用Tomcat做爲web服務器來使用。使用Apache httpd主要是它在處理靜態頁面方面的能力比Tomcat強多了。

會話親和:就是表示來自同會話的全部請求都由相同的 Tomcat 實例來處理,這種狀況下,若是Tomcat實例或所執行的服務器機器失效,也會喪失Servlet的會話數據。即便在集羣系統中執行更多的Tomcat實 例,也永遠不會複製會話數據。這樣是提升集羣性能的一種方案,但不具有有容錯能力了。

會話複製:只配置負載均衡還不行,還要 session 複製,也就是說其中任何一個 tomcat 的添加的 session ,是要同步複製到其它 tomcat , 集羣內的 tomcat 都有相同的 session,使用會話複製,則當一個Tomcat實例宕掉時,因爲至少還有另外一個Tomcat實例保有一份會話狀態數據,於是數據不會喪失。但性能會 有所下降。

其實不管是分佈式,數據緩存,仍是負載均衡,無非就是改善網站的性能瓶頸,在網站源碼不作優化的狀況下,負載均衡能夠說是最直接的手段了。其實拋開這個名詞,放開了說,就是但願用戶可以分流,也就是說把全部用戶的訪問壓力分散到多臺服務器上,也能夠分散到多個 tomcat裏,若是一臺服務器裝多個tomcat,那麼即便是負載均衡,性能也提升不了太多,不過能夠提升穩定性,即容錯性。當其中一個主tomcat 當掉,其餘的tomcat也能夠補上,由於tomcat之間實現了Session共享。待tomcat服務器修復後再次啓動,就會自動拷貝全部 session數據,而後加入集羣。這樣就能夠不間斷的提供服務。若是要真正從本質上提高性能,必需要分佈到多臺服務器。

8 Linux基礎

8.1 Linux啓動原理

CMOS:記錄 各項硬件參數且嵌入在主板上面的存儲器; BIOS:一個寫入到主板上的一個韌體(韌體就是寫入到硬件上的一個程序)。BIOS就是在開機的時候計算機系統會主動執行的第一個程序了。

  1. 首先加載BIOS程序,經過BIOS程序去 加載CMOS信息,取得主機的各項硬件配置,並開始進行開機自檢,依據設置取得第一個可啓動的設備
  2. 加載執行第一個啓動設備內MBR的Boot Loader
  3. 依據Boot Loader的 設置加載Kernel,Kernel會開始檢測硬件與加載驅動程序;
  4. 在硬件驅動成功後, Kernel會主動調用init進程,而init會取得run-level信息;
  5. init執行 /etc/rc.d/rc.sysinit文件來準備軟件執行的操做環境(如網絡,時區等);
  6. init執行 run-level的各個服務啓動(script方式);
  7. init執行 /etc/rc.d/rc.local文件;
  8. init執行 終端模擬程序mingetty來啓動login進程,最後就等待用戶登陸;

8.2 Linux命令行工具

top實時顯示系統中各個進程的資源佔用情況。前半部分是系通通計信息,後半部分是進程佔用資源情況信息。

sar週期性地對內存和CPU使用狀況進行採樣。查看CPU使用狀況:sar -u 1 3;查看內存使用狀況:sar -r 1 3;查看I/O使用狀況:sar -b 1 3

vmstat : 週期性地統計CPU 內存 swap 使用狀況等信息。vmstat 1 3

iostat : 週期性查看I/O信息。iostat 1 2

pidstat:功能強大的性能檢測工具, 不只能夠監視進程的CPU,I/O,內存資源,也能夠監視線程的性能狀況

  1. 查看CPU使用狀況: pidstat -p 1187 -u 1 3【-t 參數將系統性能的監控細化到線程級別】
  2. 查看內存使用狀況: pidstat -p 1187 -r 1 3 【-t 參數將系統性能的監控細化到線程級別】
  3. 查看I/O使用狀況: pidstat -p 1187 -d 1 3 【-t 參數將系統性能的監控細化到線程級別】

netstat用於查看各類網絡相關信息,如網絡鏈接,路由表,接口狀態 (Interface Statistics),masquerade 鏈接,多播成員 (Multicast Memberships) 等等。

netstat -na 來顯示全部鏈接的端口並用數字表示

mpstat用於獲取 CPU 相關統計信息。mpstat -P ALL 5 2 顯示了系統中 CPU 的各類統計信息。–P ALL 選項指示該命令顯示全部 CPU 的統計信息。參數 5 2 指示該命令每隔 5 秒運行一次,共運行 2 次。

pmap:report memory map of a process(查看進程的內存映像信息)。

pmap -d 1

-x   extended       Show the extended format. 顯示擴展格式

 -d   device         Show the device format.   顯示設備格式

 -q   quiet          Do not display some header/footer lines. 不顯示頭尾行

 -V   show version   Displays version of program. 顯示版本複製代碼
相關文章
相關標籤/搜索