
2016年換了新工作,這期間到各大公司進行面試,面試前在網(wǎng)上搜索了最新的java面試寶典以及java筆試題100道等等,面試過程中信心滿滿,在做完幾家企業(yè)的java筆試題以及回答面試官面試題后,發(fā)現(xiàn)之前的面試準備雖然費了洪荒之力,但是面試結(jié)果竟不盡人意。在親身經(jīng)歷幾次挫折后終于成功獲得心儀單位的offer,我的之前親身經(jīng)歷,真的是血淋淋的前車之鑒?。∫惶?016年最新版java面試考點將助你不費洪荒之力搞定java面試,現(xiàn)良心整理之作,供后來者參考,把如下考點搞清楚通過筆試面試應該問題不大?,F(xiàn)呈上干貨如下,共勉!
今年考點集中在:線程、并發(fā)、以及流行框架的源碼和架構這幾個方面。
1)什么是進程?
進程是執(zhí)行著的應用程序,而線程是進程內(nèi)部的一個執(zhí)行序列。一個進程可以有多個線程。線程又叫做輕量級進程。
2)什么是線程?
線程是進程的子集,一個進程可以有很多線程,每條線程并行執(zhí)行不同的任務。不同的進程使用不同的內(nèi)存空間,而所有的線程共享一片相同的內(nèi)存空間。
3)java有三種方式可以用來創(chuàng)建線程
- java不支持類的多重繼承,但允許你調(diào)用多個接口
1.繼承Thread類 最簡單的 new 方法,繼承一個線程類
2.實現(xiàn)Runnable接口 當需要繼承其他類的功能時,選runnable接口
3.借助框架程序 可用Executor框架來創(chuàng)建線程池,線程池可以限制線程的數(shù)量并且可以回收再利用這些線程
4)概括解釋線程在執(zhí)行過程中存在如下幾種狀態(tài),注意了解其之間的區(qū)別。
- 就緒(Runnable):線程準備運行,不一定立馬就能開始執(zhí)行。
- 運行中(Running):進程正在執(zhí)行線程的代碼。
- 等待中(Waiting): 線程處于阻塞的狀態(tài),等待外部的處理結(jié)束。
- 睡眠中(Sleeping):線程被強制睡眠。
- I/O阻塞(Blocked on I/O):等待I/O操作完成。
- 同步阻塞(Blocked on Synchronization):等待獲取鎖。
- 死亡(Dead):線程完成了執(zhí)行。
5)如何創(chuàng)建守護線程?
使用Thread類的setDaemon(true)方法可以將線程設置為守護線程,需要注意的是,需要在調(diào)用start()方法前調(diào)用這個方法,否則會拋出IllegalThreadStateException異常。
6)用戶線程和守護線程(Daemon線程)有什么區(qū)別?
當我們在Java程序中創(chuàng)建一個線程,它就被稱為用戶線程。一個守護線程是在后臺執(zhí)行并且不會阻止JVM終止的線程。當沒有用戶線程在運行的時候,JVM關閉程序并且退出。一個守護線程創(chuàng)建的子線程依然是守護線程。
守護進程能被jvm終止退出,用戶進程不能被jvm終止。
daemon線程,是指在程序運行的時候在后臺提供一種通用服務的線程,并且這個線程并不屬于程序中不可或缺的部分。
7)如何確保線程安全?
在Java中可以有很多方法來保證線程安全——同步,使用原子類(atomic concurrent classes),實現(xiàn)并發(fā)鎖,使用volatile關鍵字,使用不變類和線程安全類。
同步synchronized
同步塊大家都比較熟悉,通過 synchronized 關鍵字來實現(xiàn);所有加上 synchronized 的方法和塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠訪問。
volatile 關鍵字
volatile 是一個特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile 變量可以保證下一個讀取操作會在前一個寫操作之后發(fā)生。線程都會直接從內(nèi)存中讀取該變量并且不緩存它。這就確保了線程讀取到的變量是同內(nèi)存中是一致的。
ThreadLocal 變量
ThreadLocal 是Java里一種特殊的變量。每個線程都有一個 ThreadLocal 就是每個線程都擁有了自己獨立的一個變量,競爭條件被徹底消除了。如果為每個線程提供一個自己獨有的變量拷貝,將大大提高效率。首先,通過復用減少了代價高昂的對象的創(chuàng)建個數(shù)。其次,你在沒有使用高代價的同步或者不變性的情況下獲得了線程安全。
8) 線程sleep 和wait 的區(qū)別
sleep指線程進入休眠狀態(tài),保持對象鎖,僅釋放cpu。
wait指線程處于進入等待狀態(tài),釋放對象鎖,釋放cpu。
sleep(100L)意思為:保持對象鎖,線程休眠100毫秒
wait(100L)意思為:釋放對象鎖,線程等待100毫秒。
不同在于sleep方法是Thread類中的方法,調(diào)用它的時候不會釋放鎖;wait方法是Object類中的方法,調(diào)用它的時候會釋放鎖。
Java程序中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用于線程間通信,如果等待條件為真且其它線程被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前線程停止執(zhí)行一段時間,但不會釋放鎖。需要注意的是,sleep()并不會讓線程終止,一旦從休眠中喚醒線程,線程的狀態(tài)將會被改變?yōu)镽unnable,并且根據(jù)線程調(diào)度,它將得到執(zhí)行。
9) Thread 類中的start() 和 run() 方法有什么區(qū)別?
start()方法被用來啟動新創(chuàng)建的線程,使該被創(chuàng)建的線程狀態(tài)變?yōu)榭蛇\行狀態(tài)。
當你調(diào)用run()方法的時候,沒有新的線程啟動,只會是在原來的線程中調(diào)用,這個方法同普通類的run方法一樣。
- Java中Runnable和Callable有什么不同?
Runnable:JDK1.0開始就有了,僅是執(zhí)行Runnable的run()方法沒有返回結(jié)果。
Callable是在JDK1.5增加的。不僅執(zhí)行,Callable的 call() 方法可以返回值和拋出異常,且還可以返回裝載有計算結(jié)果的Future對象。
11) 死鎖
多線程,競爭資源,非法進程推進程序,(循環(huán)等待)。
處理策略 :鴕鳥策略,預防策略,避免策略,檢測和恢復策略
int、integer的區(qū)別
1)int是基本數(shù)據(jù)類型,integer是int的封裝類(引用類型)作為類的成員變量初始值不同,一個為0,一個為null。
3)直接賦值的時候,在【-128-127】范圍內(nèi)int=10和integer=10是一樣的。
4)有new integer值的時候,對象里存的是引用地址,故不能用==直接比較,而應該封裝類的方法equals來判斷。
整型數(shù)據(jù)類型長度:byte(8bits)、short(16bits)、int(32bits)、long(64bits),與平臺無關。String類和StringBuffer類的區(qū)別
stringbuffer區(qū)別于string的地方在于:多用于處理動態(tài)的字符,對字符進行增加或刪除。
StringBuilder:線程非安全的,速度快,適用于單線程
StringBuffer: 線程安全的,速度慢,適用于多線程
14)、&和&&的區(qū)別?
&是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)。
15)抽象類和接口的區(qū)別
抽象類是對類的抽象,是可以擁有自己的成員變量和具體方法實現(xiàn)的類;而接口是對行為的抽象,沒有具體的實現(xiàn)方法,主要視為了實現(xiàn)多繼承。
16)java的內(nèi)存管理(jvm優(yōu)化)
【堆、棧、方法區(qū)、程序計算器】



jvm將內(nèi)存分為:堆內(nèi)存、棧內(nèi)存
或者:新生代(young generations)、老年代(older generations)、永久代
堆內(nèi)存: 年輕代和年老代。
新生代就是存放新建的對象,如果gc沒有回收的對象就會進入老年代。
17)gc垃圾回收
意義:jvm的系統(tǒng)線程自動執(zhí)行垃圾回收gc,既可以釋放沒用的對象,也可以清除內(nèi)存記錄碎片。
垃圾回收算法:(1)發(fā)現(xiàn)無用信息對象;(2)回收被無用對象占用的內(nèi)存空間,使該空間可被程序再次使用。
垃圾回收算法可以分為三類,都基于標記-清除(復制)算法:Serial算法(單線程)、并行算法、并發(fā)算法。
程序員可以通過** System.gc()方法去提交清理垃圾的請求,由jvm自己來確定是否進行回收。
** 減少GC開銷
(1)不要顯式調(diào)用System.gc()
(2)盡量減少臨時對象的使用
(3)盡量使用StringBuffer,而不用String來累加字符串
(4)盡量少用靜態(tài)對象變量
- 內(nèi)存泄漏(memory leak)和內(nèi)存溢出(out of memory)的區(qū)別
內(nèi)存溢出:指程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請了一個integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。
jvm 何時拋出OutOfMemoryException:并不是內(nèi)存被耗空的時候才拋出
1)JVM98%的時間都花費在內(nèi)存回收
2)每次回收的內(nèi)存小于2%內(nèi)存泄露:指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴重,無論多少內(nèi)存,遲早會被占光。
或【內(nèi)存中存在可達、無用的對象,且不會被GC回收,一直占用著內(nèi)存。
該對象就是內(nèi)存泄漏的對象 】泄漏強調(diào)無法收回,占用內(nèi)存;溢出強調(diào)不夠,無法滿足。
- 內(nèi)存溢出常見解決辦法
第1種 OutOfMemoryError: PermGen space
永久性存在的Permanent Generation space不夠了。
JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m"
可以通過 增加java虛擬機中的參數(shù)大小。
第2種 OutOfMemoryError:Java heap space
檢查程序是否有冗余的對象,調(diào)整參數(shù),增加Java虛擬機中Xms(初始堆大小)和Xmx(最大堆大?。﹨?shù)的大小。set JAVA_OPTS= -Xms256m -Xmx1024m。
20) 如何監(jiān)控tomcat的內(nèi)存情況
tomcat是通過java跑起來的,查看對應的pid之后,可以通過jvm自帶的監(jiān)控工具
jstat和jconsole來進行查看內(nèi)存中的堆內(nèi)存的和非堆內(nèi)存的內(nèi)容。
21)如何實現(xiàn)一個servlet?
- 實現(xiàn)Servlet接口* 繼承GenericServlet類* 繼承HttpServlet類
創(chuàng)建一個自定義的servlet類,實現(xiàn)java中servlet接口,該接口包含5個方法。
或者繼承 GenericServlet類 或者 繼承HttpServlet類。
- Servlet生命周期?
分為三個階段:
1,初始化階段 調(diào)用init()方法
2,響應客戶請求階段 調(diào)用service()方法
3,終止階段 調(diào)用destroy()方法
23)MVC的各個部分都有那些技術來實現(xiàn)?如何實現(xiàn)?
MVC是三個單詞的縮寫,分別為:模型(Model),視圖(View)和控制Controller)。 MVC模式的目的就是實現(xiàn)Web系統(tǒng)的職能分工。 Model層實現(xiàn)系統(tǒng)中的業(yè)務邏輯,通??梢杂肑avaBean或EJB來實現(xiàn)。 View層用于與用戶的交互,通常用JSP來實現(xiàn),freemarker velocity。 Controller層是Model與View之間溝通的橋梁,它可以分派用戶的請求并選擇恰當?shù)囊晥D以用于顯示,同時它也可以解釋用戶的輸入并將它們映射為模型層可執(zhí)行的操作,通??梢杂肧ervlet來實現(xiàn)。
24) java并發(fā)
并發(fā)的一個重要原因是提高執(zhí)行效率
為了實現(xiàn)并發(fā),操作系統(tǒng)層面提供了多進程。
還有一種比較輕量的并發(fā)實現(xiàn)是使用線程,一個進程可以包含多個線程。 Java 語言中支持多線程。
25)線程協(xié)作
線程的通信:下面3個方法只能在同步塊里面被調(diào)用
wait() 使線程進入睡眠狀態(tài)
notify() 隨機喚醒一個等待的線程,它將獲得一次搶奪鎖的機會notifyAll() 喚醒所有等待的線程
26)死鎖【死鎖有四個必要條件,打破一個即可去除死鎖】
四個必要條件:
互斥條件。 一個資源每次只能被一個進程使用。
請求與保持條件:一個線程因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:線程已獲得的資源,在末使用完之前,不能強行剝奪。
循環(huán)等待條件:若干線程之間形成一種頭尾相接的循環(huán)等待資源關系。
友情提示
我是和奇谷樸,一個上班族,讀完我的文章如果今年面試通過了,記得打賞、關注和點贊哦!么么噠??!