java后端研发经典面试题总结二
四種讀取XML文件讀取的辦法
1.DOM生成和解析XML文檔
為XML文檔的已解析版本定義了一組接口。解析器讀入整個文檔,然后構建一個駐留內存的樹結構。
優點:整個文檔樹在內存中,便于操作;支持刪除,修改,重新排列等。
缺點: 把整個文檔調入內存,存在很多無用的節點,浪費了時間和空間。
2.SAX為解決DOM
1、邊讀邊解析,應用于大型XML文檔
2、只支持讀
3、訪問效率低
4、順序訪問
3.DOM4J生成和解析XML文檔(解析工具) 性能最好 SUM的JAXM也大量采用DOM4J
HIBERNATE采用DOM4J
雖然DOM4J代表了完全獨立的開發結果,但最初,它是JDOM的一種智能分支。它合并了許多超出基本XML文檔表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文檔或流化文檔的基于事件的處理。它還提供了構建文檔表示的選項,它通過DOM4J API和標準DOM接口具有并行訪問功能。從2000下半年開始,它就一直處于開發之中。
為支持所有這些功能,DOM4J使用接口和抽象基本類方法。DOM4J大量使用了API中的Collections類,但是在許多情況下,它還提供一些替代方法以允許更好的性能或更直接的編碼方法。直接好處是,雖然DOM4J付出了更復雜的API的代價,但是它提供了比JDOM大得多的靈活性。在添加靈活性、XPath集成和對大文檔處理的目標時,DOM4J的目標與JDOM是一樣的:針對Java開發者的易用性和直觀操作。它還致力于成為比JDOM更完整的解決方案,實現在本質上處理所有Java/XML問題的目標。在完成該目標時,它比JDOM更少強調防止不正確的應用程序行為。DOM4J是一個非常非常優秀的Java XML API,具有性能優異、功能強大和極端易用使用的特點,同時它也是一個開放源代碼的軟件。如今你可以看到越來越多的Java軟件都在使用DOM4J來讀寫XML,特別值得一提的是連Sun的JAXM也在用DOM4J.4.JDOM
JDOM
優點:①是基于樹的處理XML的Java API,把樹加載在內存中
②沒有向下兼容的限制,因此比DOM簡單③速度快,缺陷少④具有SAX的JAVA規則缺點:
①不能處理大于內存的文檔②JDOM表示XML文檔邏輯模型。不能保證每個字節真正變換。③針對實例文檔不提供DTD與模式的任何實際模型。④不支持與DOM中相應遍歷包。最適合于:JDOM具有樹的便利,也有SAX的JAVA規則。在需要平衡時使用
如何防止Sql注入
有兩種辦法
1.第一種消毒,通過正則匹配過濾請求數據中可能注入的SQL。
2.使用預編譯手段preparedStatemengt。
DB第一范式,第二范式,第三范式
第一范式:沒一列屬性不可再分,沒有多值屬性
第二范式:在符合第一范式的基礎上,存在主鍵
第三范式:在符合第二范式的基礎上,非關鍵字獨立于其他的非關鍵字,并且依賴關鍵字。不能存在傳遞依賴。
**public、protected、private、**默認權限
private:用于修飾類和方法,只允許該類訪問。
默認:只允許在同一個類和同一個包中進行訪問。
protected:用于修飾類和方法,允許該類和子類訪問以及同一個包中訪問。
public:用于修飾類和方法,允許該包下面和其他包的訪問,即在全局范圍都可以訪問。
數據庫事務
事務的特性:
原子性:事務是不可再分的;
一致性:事務的實行前后,數據庫的狀態保持一致;
隔離性:事務的并發訪問,事務之間的執行互不干擾;
持久性:事務結束后數據永久保存在數據庫中。
什么是臟讀?
臟讀就是一個事務讀取了該數據并且對該數據做出了修改,另一個事務也讀取了該修改后的數據但是前一個事務并沒有提交,這是臟數據。
讀取到保存在數據庫內存中的數據。
什么是不可重復讀?
一個事務:在同一個事務中讀取同一數據,得到的內容不同。一個事務讀取另外一個事務更新的數據,導致二次的查詢的數據不一致。
什么是幻讀?
幻讀是當事務不獨立發生的。比如一個事務刪除了所有數據,另一個事務又插入了一條,那么第一個事務的用戶會發現表中還沒有修改的數據行。一個事務讀取到另外一個事務提交的數據,導致查詢的結果不一致的問題。
數據庫的隔離級別:
Read uncommitted:未提交讀:三中都有可能發生
Read committed :已提交讀 避免臟讀
Repeated read:重復讀:避免臟讀 不可重復讀
Serializable:串行化讀 都可以避免
WebService到底是什么
一言以蔽之:WebService是一種跨編程語言和跨操作系統平臺的遠程調用技術。所謂跨編程語言和跨操作平臺,就是說服務端程序采用java編寫,客戶端程序則可以采用其他編程語言編寫,反之亦然!跨操作系統平臺則是指服務端程序和客戶端程序可以在不同的操作系統上運行。
所謂遠程調用,就是一臺計算機a上的一個程序可以調用到另外一臺計算機b上的一個對象的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬調用的轉賬方法的代碼其實是跑在銀行服務器上。再比如,amazon,天氣預報系統,淘寶網,校內網,百度等把自己的系統服務以webservice服務的形式暴露出來,讓第三方網站和程序可以調用這些服務功能,這樣擴展了自己系統的市場占有率,往大的概念上吹,就是所謂的SOA應用。其實可以從多個角度來理解WebService,從表面上看,WebService就是一個應用程序向外界暴露出一個能通過Web進行調用的API,也就是說能用編程的方法通過Web來調用這個應用程序。我們把調用這個WebService的應用程序叫做客戶端,而把提供這個WebService的應用程序叫做服務端。從深層次看,WebService是建立可互操作的分布式應用程序的新平臺,是一個平臺,是一套標準。它定義了應用程序如何在Web上實現互操作性,你可以用任何你喜歡的語言,在任何你喜歡的平臺上寫Web service ,只要我們可以通過Web service標準對這些服務進行查詢和訪問。WebService平臺需要一套協議來實現分布式應用程序的創建。任何平臺都有它的數據表示方法和類型系統。要實現互操作性,WebService平臺必須提供一套標準的類型系統,用于溝通不同平臺、編程語言和組件模型中的不同類型系統。Web service平臺必須提供一種標準來描述Web service,讓客戶可以得到足夠的信息來調用這個Web service。最后,我們還必須有一種方法來對這個Web service進行遠程調用,這種方法實際是一種遠程過程調用協議(RPC)。為了達到互操作性,這種RPC協議還必須與平臺和編程語言無關。
java中鎖的優化
1.減少鎖持有的時間,可以減少其它線程的等待時間,不能讓一個線程一直控制著某個鎖不釋放,導致競爭加劇。
2.減少鎖的粒度,合適的鎖的代碼塊,可以減少競爭,控制鎖的范圍。
3.鎖分離,將鎖安功能劃分,比如讀寫鎖,讀讀不互斥,讀寫互斥,寫寫互斥,保證了線程的安全,提高了性能。比如阻塞隊列中的take和put
4.鎖粗化,如果對同一個鎖不停的進行請求,同步和釋放,這個消耗是非常的大的,所以適當的時候可以粗化。
5.鎖消除,編譯器可以幫助我們優化比如一些代碼根本不需要鎖。
虛擬機內的鎖優化
1.偏向鎖:偏向當前已經占有鎖的線程,在無競爭的時候,之前獲得鎖的線程再次獲得鎖時,會判斷是否偏向鎖指向我,那么該線程將不用再次獲得鎖,直接進入同步塊。
2.輕量級鎖:偏向鎖失敗后,利用cas補救補救失敗就會升級為重量級鎖。
3.自旋鎖:會做空操作,并且不停地嘗試拿到這個鎖。
java中一億個數找前10000個最大的
先利用Hash法去重復,去除大量的之后 然后等量的分成100份 用小頂堆 來獲得10000個,再把所有的1萬個都合在一起就OK
java中線程的狀態
java中的線程的狀態有5種(新建、就緒、運行、阻塞、結束)
1.新建:創建后尚未啟動的線程處于這種狀態,新建出一個線程對象。
2.就緒狀態:當針對該對象掉用了start()方法,該線程等待獲取CPU的使用權
3.運行狀態:在就緒狀態下,獲得了CPU處于運行狀態。
4.阻塞:
等待阻塞:運行的線程執行wait方法,JVM會把該線程放入等待池
同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被其他的線程鎖占用,則jvm會把該線程放入鎖池中。
其他阻塞:運行的線程在執行sleep()方法或者join()方法時,或者發出IO請求,JVM會把線程置為阻塞狀態。
5.結束:
也就是我們的死亡,表明線程結束。
Maven的生命周期
maven有三套相互獨立的生命周期
1.clean生命周期
pre-clean,clean,post-clean
2.default生命周期 構建項目
1.validate:驗證工程是否正確,所有需要的資源是否可用
2.compile:編譯項目源代碼
3.test:使用合適的單元框架來測試已編譯的源代碼。
4.Package:把已編譯的代碼打包成可發布的格式,jar。
4)Package:把已編譯的代碼打包成可發布的格式,比如jar。
5)integration-test:如有需要,將包處理和發布到一個能夠進行集成測試的環境。
6)verify:運行所有檢查,驗證包是否有效且達到質量標準。
7)install:把包安裝到maven本地倉庫,可以被其他工程作為依賴來使用。
8)Deploy:在集成或者發布環境下執行,將最終版本的包拷貝到遠程的repository,使得其他的開發者或者工程可以共享。
site生命周期:建立和發布項目站點,phase如下
1)pre-site:生成項目站點之前需要完成的工作
2)site:生成項目站點文檔
3)post-site:生成項目站點之后需要完成的工作
4)site-deploy:將項目站點發布到服務器
數據庫索引
什么是索引?
(1)索引是對記錄集多個字段進行排序的方法。
(2)也是一個數據結構,在一張表中為一個字段創建索引,將創建另外一個數據結構,包含字段的數值以及指向相關記錄的指針,就可以對該數據結構進行二分法排序,當需要查詢時就可以降低時間復雜度。
優勢:快速存取數據;保證數據記錄的唯一性;實現表和表之間的參照完整性;在使用order by group by子句進行數據的檢索時,利用索引可以減少排序和分組的時間。
弊端:建立索引表也是會需要額外的空間。
索引的工作原理:
在對表中記錄進行搜索時并不是對表中的數據進行全部的掃描遍歷,而是查看在索引中定義的有序列,一旦在索引中找到了要查詢的記錄,就會得到一個指針,它會指向相應的表中數據所保存的位置。索引的類型:
(1)聚集索引:數據頁在物理上的有序的存儲,數據頁的物理順序是按照聚集索引的順序進行排列。在聚集索引中數據頁聚集索引的葉子節點,數據頁之間通過雙向的鏈表形式相連接,實際的數據存儲在葉節點中。
(2)非聚集索引:葉子節點不存放具體的數據頁信息,只存放索引的鍵值。非聚集索引的葉子節點包含著指向具體數據的指針,數據頁之間沒有連接,是相對獨立的。
(3)唯一索引:在整個表中僅僅會出現一次(主鍵約束/UNIQUE)
(4)非唯一索引:在提取數據時允許出現重復的值。
(5)單一索引和組合索引
[哪些情況下索引會失效?]
1.條件中有or但是前后沒有同時使用索引
2.多列索引,不是使用前面部分
3.like查詢是以%開頭
4.字符類型應該加單引號 防止轉換為int類型
數據庫查詢優化(Sql)
1、應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
2、對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
3、應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
4、盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5、下面的查詢也將導致全表掃描:(不能前置百分號)
select id from t where name like ‘�c%’
若要提高效率,可以考慮全文檢索。
6、in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對于連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
7、如果在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8、應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
9、應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)=’abc’–name以abc開頭的id
select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
應改為:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′
10、不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
11、在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使 用,并且應盡可能的讓字段順序與索引順序相一致。
12、不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(…)
13、很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
14、并不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段 sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。
15、索引并不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。
16.應盡可能的避免更新 clustered 索引數據列,因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那么需要考慮是否應將該索引建為 clustered 索引。
17、盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會 逐個比較字符串中每一個字符,而對于數字型而言只需要比較一次就夠了。
18、盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然要高些。
19、任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。
20、盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。
21、避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
22、臨時表并不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對于一次性事件,最好使 用導出表。
23、在新建臨時表時,如果一次性插入數據量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然后insert。
24、如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統表的較長時間鎖定。
25、盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。
26、使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。
27、與臨時表一樣,游標并不是不可使用。對小型數據集使用 FAST_FORWARD 游標通常要優于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時 間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。
28、在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句后向客戶端發送 DONE_IN_PROC 消息。
29、盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
30、盡量避免大事務操作,提高系統并發能力。查詢sql語句中哪些比較慢
1.慢查詢日志,一般設置查詢超過兩秒就記錄
2.processlist:顯示哪些線程正在運行.
3.explain關鍵字可以讓我們更好的優化
數據庫設計優化:
1.反范式設計,盡量是單表,可以高效利用索引
2.可以使用查詢緩存,Mysql也會自帶查詢緩存
3.盡量查詢通過搜索引擎查不通過我們
4.key,value數據庫
鎖的優化策略
1.讀寫分離,鎖分離
2.減少鎖持有時間,可以減少其他的鎖的持有時間
3.以正確的順序獲得和釋放鎖
4.適當的鎖的范圍擴大或者縮小,控制鎖的粒度
Spring Bean中作用域
singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例。
prototype:原型模式,每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例。
request:對于每次HTTP請求,使用request定義的Bean都將產生一個新實例,即每次HTTP請求將會產生不同的Bean實例。只有在Web應用中使用Spring時,該作用域才有效。
session:對于每次HTTP Session,使用session定義的Bean都將產生一個新實例。同樣只有在Web應用中使用Spring時,該作用域才有效。
Global****session:每個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。典型情況下,僅在使用portlet context的時候有效。同樣只有在Web應用中使用Spring時,該作用域才有效。
java中啟定時任務
1.利用sleep特性//休眠
2.time和timerTask//定時器
3.ScheduledExecutorService service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);
//任務調度服務
操作系統如何進行分頁調度
用戶程序的地址空間被劃分成若干固定大小的區域,稱為“頁”,相應地,內存空間分成若干個物理塊,頁和塊的大小相等。可將用戶程序的任一頁放在內存的任一塊中,實現了離散分配。
linux內核的三種主要調度策略:
1,SCHED_OTHER 分時調度策略,
2,SCHED_FIFO實時調度策略,先到先服務
3,SCHED_RR實時調度策略,時間片輪轉
TCP和UDP相關
TCP通過什么方式提供可靠性:
1.超時重發,發出報文段要是沒有收到及時的確認,會重發。
2.數據包的校驗,也就是校驗首部數據和。
3.對失序的數據重新排序
4.進行流量控制,防止緩沖區溢出
5.快重傳和快恢復
6.TCP會將數據截斷為合理的長度
TCP和UDP的區別:
1.UDP是無連接的,TCP必須三次握手建立連接
2.UDP是面向報文,沒有擁塞控制,所以速度快,適合多媒體通信要求,比如及時聊天,支持一對一,一隊多。多對一,多對多。
3.TCP只能是一對一的可靠性傳輸
TCP的RPC,在協議棧的下層,能夠靈活的對字段進行定制,減少網絡傳輸字節數,降低網絡開銷,提高性能,實現更大的吞吐量和并發數。但是實現代價高,底層復雜,難以得到開源社區的支持,難以實現跨平臺
集群調優
1.load
load是被定義為特定時間間隔內運行隊列中的平均線程數,uptime查看,一般load不大于3,我們認為負載是正常的,如果每個CPU的線程數大于5,表示負載就非常高了。
2.CPU利用率
查看cpu的消耗的情況命令:top | grep Cpu
查看磁盤的剩余空間命令:df -h
查看系統的內存的使用情況:free -m
心跳檢測方法
1.使用ping命令
對于full gc導致不響應,網絡攻擊這種 ping展示不明確
2.使用curl
訪問我們的自測地址
3.對不同的功能使用curl檢測,在response中加入狀態頭,表示正常
可以計算qps通過28原則
innodb存儲引擎通過預寫事務日志的方式保障事務的原子性,也就是在寫入數據之前,先將數據操作寫入日志,這種成為預寫日志
輕量級鎖認為在程序運行過程中,絕大部分的鎖,在整個同步周期內都是不存在競爭的,利用cas操作避免互斥開銷。
偏向鎖是jdk1.6中引入的一項優化,甚至可以省掉CAS操作,偏向鎖偏向第一個獲得他鎖的線程,如果在接下來執行過程中,這個鎖沒有被其他線程獲取,則持有偏向鎖的線程永遠不需要同步。
GC調優
查看GC日志,根據GC日志來優化
我們可以通過jps找到我們虛擬機正在運行的進程。參數 通過jps -help了解。
Jstat -gc 或者 -gcutil 查看堆使用情況-class 配合Jps得到進程
BTrace原理利用hotspot虛擬中的熱替換,把代碼動態的替換到java程序內,可在不需要重啟的時候就可以排除問題
JConsole
我們也可以使用JConsole來分析這是一個圖形化的,比較容易讓我們操作
使用VisualVM 進行遠程連接 使用JMX方式,也有修改tomcat的catalina就行了
內部類去訪問外部變量,為什么需要加final?
題目有點問題,并不是所有的外部變量才加final,我們的內部類訪問我們的成員變量就不需要加final,但是訪問局部變量就必須要加final,因為方法(main方法)結束我們棧幀也就銷毀了,但是我們內部類在堆中并沒有被銷毀,如果引用了成員變量,這時候被銷毀了肯定是不行的,所以我們就需要成員變量設置為final,讓其在方法(main方法)結束時不會被銷毀。
泛型
泛型的作用:在我們沒有泛型的時候,我們通過對Object的引用來對參數的任意化,任意化有個缺點就是要做顯示的強制類型轉換,強制轉換有一個不好的地方是運行的時候才會報錯,泛型的好處實在編譯的時候檢查類型安全,所以泛型的特點就是簡單安全,泛型的原理是類型擦除,java的泛型是偽泛型,在編譯期間,所有的泛型信息都會被擦除掉。在生成的java字節碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會在編譯器編譯的時候去掉。比如List信息在編譯后都是List。
nginx和apache的對比
1.nginx相對于apache來說
(1)輕量級占用的內存少;
(2)抗并發,nginx是異步非阻塞,apache是阻塞的,在高并發的情況下,nginx的性能優;
(3)高度模塊化的設計,編寫模塊相對簡單;
(4)社區活躍,各種高性能模塊有。
適合場景:apache適合于動態的請求,而負載均衡和靜態請求適合nginx,nginx采用的是epoll,并且有自己的一套sendfile系統,減少在內存中的賦值次數。
2.apache 相對于nginx 的優點:
(1)rewrite ,比nginx 的rewrite 強大 ;
(2)模塊超多,基本想到的都可以找到 ;
(3)少bug ,nginx 的bug 相對較多 ;
(4)超穩定 。
** 線程****、進程的****共享和獨立**
共享的部分:
1.進程代碼段
2.進程的公有數據(利用這些共享的數據,線程很容易的實現相互之間的通訊)
3.進程打開的文件描述符、
4.信號的處理器、
5.進程的當前目錄
6.進程用戶ID與進程組ID
線程獨有的內容包括:
1.線程ID
2.寄存器組的值
3.線程的堆棧
4.錯誤返回碼
5.線程的信號屏蔽碼
最大的優勢就是線程極高的執行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,線程的性能優勢就越明顯。
第二大優勢就是不需要多線程的鎖機制,因為只有一個線程,也不存在同時寫變量沖突,在線程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多。
簡單的說一下nginx的優點
1.作為高性能的web服務器:相比Apache,Nginx使用更少的資源,支持更多的并發連接,體現更高的效率,這點讓Nginx受到虛擬主機提供商的歡迎。一個Nginx實例能夠輕松支持高達5萬并發。
2.作為負載均衡服務器:Nginx即可以在內部直接支持PHP,也可以支持作為HTTP代理服務器對外進行服務,獨有的send files系統,減少文件復制次數。
3.作為**郵件代理服務器:**也比Apache好很多。
4.Nginx安裝簡單,配置文件非常簡潔。啟動容易,7*24小時幾乎不間斷,可以進行熱更新。
BIO
在BIO中讀和寫都是同步阻塞的,阻塞的時間取決于對方I/O線程的處理速度和網絡的傳輸速度。本質上來講,我們是無法保證生產環境的網絡狀況和對端的應用程序可以足夠快,應用程序是不應該依賴對方的處理速度,它的可靠性就非常差。BIO就算用線程池實現,要是所有可用線程都被阻塞到故障點中,后續的所有I/O消息都將在隊列中排隊。
NIO
(1)提供了高速,面向塊的I/O。
(2)在NIO中所有數據都是用緩沖區來處理的,也就是使用我們的jvm中的direct memory(直接內存)。緩沖區是一個數組,但是緩沖區不僅僅是一個數組,緩沖區提供了對數據的結構化訪問以及維護讀寫位置等信息。
(3)在NIO中channel****(通道)也是特別重要的他是我們數據讀寫的通道,一般來說流比如inputStream和outputStream都是單向的,而通道是雙向的,是全雙工的。
(4)多路復用器Selector也是比較重要的,掌握它對于我們的NIO編程來說是比較重要的。多路復用器提供選擇已經就緒的任務的能力。Selector會不斷輪訓注冊在其上的Channel,如果某個Channel上面發生讀或者寫事件,這個Channel就處于就緒狀態,會被Selector輪詢出來,通過Selection Key可以獲取就緒Channel的集合,進行后續的I/o操作。我們只需要一個線程就可以管理我們多個客戶端。
垃圾收集器
1.Serial收集器
Serial收集器是JAVA虛擬機中最基本、歷史最悠久的收集器,在JDK 1.3.1之前是JAVA虛擬機新生代收集的唯一選擇。Serial收集器是一個單線程的收集器,但它的“單線程”的意義并不僅僅是說明它只會使用一個 CPU或一條收集線程去完成垃圾收集工作,更重要的是在它進行垃圾收集時,必須暫停其他所有的工作線程,直到它收集結束。Serial收集器到JDK1.7為止,它依然是JAVA虛擬機運行在Client模式下的默認新生代收集器。它也有著優于其他收集器的地方:簡單而高 效(與其他收集器的單線程比),對于限定單個CPU的環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集 效率。在用戶的桌面應用場景中,分配給虛擬機管理的內存一般來說不會很大,收集幾十兆甚至一兩百兆的新生代(僅僅是新生代使用的內存,桌面應用基本上不會 再大了),停頓時間完全可以控制在幾十毫秒最多一百多毫秒以內,只要不是頻繁發生,這點停頓是可以接受的。所以,Serial收集器對于運行在 Client模式下的虛擬機來說是一個很好的選擇。2. Parallel(并行)收集器
這是 JVM 的缺省收集器。就像它的名字,其最大的優點是使用多個線程來通過掃描并壓縮堆。串行收集器在GC時會停止其他所有工作線程(stop-the- world),CPU利用率是最高的,所以適用于要求高吞吐量(throughput)的應用,但停頓時間(pause time)會比較長,所以對web應用來說就不適合,因為這意味著用戶等待時間會加長。而并行收集器可以理解是多線程串行收集,在串行收集基礎上采用多線 程方式進行GC,很好的彌補了串行收集的不足,可以大幅縮短停頓時間(如下圖表示的停頓時長高度,并發比并行要短),因此對于空間不大的區域(如 young generation),采用并行收集器停頓時間很短,回收效率高,適合高頻率執行。3.CMS收集器
CMS(Concurrent Mark Sweep)收集器是基于“標記-清除”算法實現的,它使用多線程的算法去掃描堆(標記)并對發現的未使用的對象進行回收(清除)。整個過程分為6個步驟,包括:初始標記(CMS initial mark)
并發標記(CMS concurrent mark)
并發預清理(CMS-concurrent-preclean)
重新標記(CMS remark)
并發清除(CMS concurrent sweep)
并發重置(CMS-concurrent-reset)
其中初始標記、重新標記這兩個步驟仍然需要“Stop The World”。初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,并發標記階段就是進行GC Roots Tracing的過程,而重新標記階段則是為了修正并發標記期間,因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一 般會比初始標記階段稍長一些,但遠比并發標記的時間短。其他動作都是并發的。需要注意的是,CMS收集器無法處理浮動垃圾(Floating Garbage),可能出現“Concurrent Mode Failure”失敗而導致另一次Full GC的產生。由于CMS并發清理階段用戶線程還在運行著,伴隨程序的運行自然還會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之后,CMS無法在本次 收集中處理掉它們,只好留待下一次GC時再將其清理掉。這一部分垃圾就稱為“浮動垃圾”。也是由于在垃圾收集階段用戶線程還需要運行,即還需要預留足夠的 內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分空間提供并發收集時的程序運作使 用。在默認設置下,CMS收集器在老年代使用了68%的空間后就會被激活,這是一個偏保守的設置,如果在應用中老年代增長不是太快,可以適當調高參數 -XX:CMSInitiatingOccupancyFraction的值來提高觸發百分比,以便降低內存回收次數以獲取更好的性能。要是CMS運行期 間預留的內存無法滿足程序需要,就會出現一次“Concurrent Mode Failure”失敗,這時候虛擬機將啟動后備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。所以說參數-XX:CMSInitiatingOccupancyFraction設置 得太高將會很容易導致大量“Concurrent Mode Failure”失敗,性能反而降低。try catch有return 在字節碼中 可以看到會出現Goto跳轉行數,跳轉到finally中的return
Tomcat總結構
最外層的Server提供接口訪問內部的Service服務。
Service服務的作用就是把Connector 在Connetor中監聽端口和Container連接起來,方便我們的操縱控制。
在tomcat中生命周期是統一的由Lifecycle來管理的
在lifecycle中有兩個方法比較重要start和stop,調用server的start會去調用自己下面所有service的start方法
Connector最重要的功能就是接受連接請求然后分配線程處理
在Container中 有4個級別Engine,Host,Context,warpper,這四個組件不是平行的,而是父子關系,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper。通常一個 Servlet class 對應一個 Wrapper,如果有多個 Servlet 就可以定義多個 Wrapper,如果有多個 Wrapper 就要定義一個更高的 Container 了,如 Context。在Host中有個value比較重要,類似于一個管道,和攔截器鏈差不多,我們在中間可以進行一些處理。
在Engine中只能添加子容器Host,不能添加父容器.Engine下可以配置多個虛擬主機Virtual Host,每個虛擬主機都有一個域名
當Engine獲得一個請求時,它把該請求匹配到某個Host上,然后把該請求交給該Host來處理Engine有一個默認虛擬主機,當請求無法匹配到任何一個Host上的時候,將交給該默認Host來處理
一個Host就類似于一個虛擬主機,用來管理應用。代表一個Virtual Host,虛擬主機,每個虛擬主機和某個網絡域名Domain Name相匹配
每個虛擬主機下都可以部署(deploy)一個或者多個Web App,每個Web App對應于一個Context,有一個Context path
當Host獲得一個請求時,將把該請求匹配到某個Context上,然后把該請求交給該Context來處理
匹配的方法是“最長匹配”,所以一個path==""的Context將成為該Host的默認Context
所有無法和其它Context的路徑名匹配的請求都將最終和該默認Context匹配。
Context 代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,理論上只要有 Context 就能運行 Servlet 了。簡單的 Tomcat 可以沒有 Engine 和 Host。
Context 最重要的功能就是管理它里面的 Servlet 實例,Servlet 實例在 Context 中是以 Wrapper 出現的,還有一點就是 Context 如何才能找到正確的 Servlet 來執行它呢?
一個Context對應于一個Web Application,一個Web Application由一個或者多個Servlet組成
Context在創建的時候將根據配置文件 C A T A L I N A H O M E / c o n f / w e b . x m l 和 CATALINA_HOME/conf/web.xml和 CATALINAH?OME/conf/web.xml和WEBAPP_HOME/WEB-INF/web.xml載入Servlet類
當Context獲得請求時,將在自己的映射表(mapping table)中尋找相匹配的Servlet類
如果找到,則執行該類,獲得請求的回應,并返回.
總結
以上是生活随笔為你收集整理的java后端研发经典面试题总结二的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软客户体验中心感受
- 下一篇: Python简介及入门