2023年Java代碼筆試題及答案大全_第1頁
2023年Java代碼筆試題及答案大全_第2頁
2023年Java代碼筆試題及答案大全_第3頁
2023年Java代碼筆試題及答案大全_第4頁
2023年Java代碼筆試題及答案大全_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

2023年Java代碼筆試題及答案大全【范文】

Java代碼筆試題及答案大全

筆試是測評考生的學(xué)問、力量、閱歷等有關(guān)素養(yǎng)的一種考試活動。那么Java代碼筆試題有哪些呢?今日整理了java筆試編程題供大家參考,一起來看看吧!

Java代碼筆試題及答案

1、運算符優(yōu)先級問題,下面代碼的結(jié)果是多少?

publicclassTest{

publicstaticvoidmain(String[]args){

intk=0;

intret=++k+k+++++k+k;

//ret的值為多少

System.err.println(ret);

}

}

解答:主要考察++i和i++的區(qū)分。++在前則先自增再賦值運算,++在后則先賦值再自增運算。因此,結(jié)果為8。

2、在Java中,以下代碼(A)正確地創(chuàng)立了一個InputStreamReader對象。

A)InuptStreamReader(newFileInputStream(“1.dat”));

B)InuptStreamReader(newFileReader(“1.dat”));

C)InuptStreamReader(newBufferReader(“1.dat”));

D)InuptStreamReader(“1.dat”);

3、下面代碼的結(jié)果是什么?

publicclassTest{

publicvoidmyMethod(Stringstr){

System.err.println(string);

}

publicvoidmyMethod(Objectobj){

System.err.println(object);

}

publicstaticvoidmain(String[]args){

Testt=newTest();

t.myMethod(null);

}

}

解答:這道題考察重載方法參數(shù)具有繼承關(guān)系時的調(diào)用問題,還有對null的熟悉。假如是一般具有繼承關(guān)系的對象分別作為參數(shù),看對象的引用,如:

classA{

}

classBextendsA{

}

publicclassTest{

publicstaticvoidmain(String[]args){

Ab1=newB();

Bb2=newB();

get(b1);//A

get(b2);//B

}

publicstaticvoidget(Aa){

System.out.println(A);

}

publicstaticvoidget(Ba){

System.out.println(B);

}

}

這道題中,Object是一切類的父類,具有繼承關(guān)系,那null是指向什么呢?null是任何引用類型的初始值,String和Object的初始值都是null,但是null會優(yōu)先匹配引用類型參數(shù)為String的方法,因此這道題答案是string。假設(shè)這道題中還有其他同是引用類型的重載方法呢?如:

publicvoidmyMethod(Integerobj){

System.err.println(Integer);

}

假如是這樣的話,調(diào)用這個方法傳入?yún)?shù)null時會報錯,他不知道選哪個方法進展匹配調(diào)用了。

4、假設(shè)今日是9月8日,下面代碼輸出什么?

publicclassTest{

publicstaticvoidmain(String[]args){

Datedate=newDate();

System.err.println(date.getMonth()++date.getDate());

}

}

解答:這道題考察的是日期中獵取的月份是從0開頭的,因此會比我們?nèi)粘5脑路萆?,這個題答案是88。

5、下面代碼的輸出結(jié)果是什么?

publicclassTest{

publicstaticvoidmain(String[]args){

doubleval=11.5;

System.err.println(Math.round(val));

System.err.println(Math.floor(val));

System.err.println(Math.ceil(val));

}

}

解答:這個是在考Math取整數(shù)的三種方法。round()是四舍五入取證,floor()是舍去小數(shù)位,ceil()是向上進一位。floor是地板ceil是天花板,一個在下,則舍去,一個在上,則向上進1。那是不是結(jié)果應(yīng)當為12、11、12呢?還要考慮返回值類型,round()返回值類型為long長整型,floor()和ceil()返回值的是double類型,因此正確的答案應(yīng)當是12、11.0、12.0。

6、編程輸出一個名目下的全部名目及文件名稱,名目之間用tab。

publicclassTest{

publicstaticvoidmain(String[]args){

newTest().read(D:/test,);

}

publicvoidread(Stringpath,Stringtab){

Filefile=newFile(path);

File[]childFiles=file.listFiles();

for(inti=0;childFiles!=nullichildFiles.length;i++){

System.err.println(tab+childFiles[i].getName());

if(childFiles[i].isDirectory()){

read(childFiles[i].getPath(),tab+\t);

}

}

}

}

這個主要是考察IO局部學(xué)問點了。

7、從鍵盤讀入10個整數(shù),然后從大到小輸出。

publicclassTest{

publicstaticvoidmain(String[]args){

Scannerin=newScanner(System.in);

//留意這里的數(shù)組,不是int的

Integer[]arr=newInteger[10];

for(inti=0;i10;i++){

arr[i]=in.nextInt();

}

Arrays.sort(arr,newComparator(){

@Override

publicintcompare(Integero1,Integero2){

if(o1o2)return-1;

if(o1o2)return1;

return0;

}

});

System.err.println(Arrays.toString(arr));

}

}

8、下面代碼的結(jié)果是什么?

publicclassTestextendsBase{

publicstaticvoidmain(String[]args){

Baseb=newTest();

b.method();

Testt=newTest();

t.method();

}

@Override

publicvoidmethod(){

System.err.println(test);

}

}

classBase{

publicvoidmethod()throwsInterruptedException{

System.err.println(base);

}

}

解答:兩次調(diào)用輸出都是test。多態(tài)的狀況下,盡管是父類的引用,調(diào)用方法時,還是調(diào)用子類的方法。

9、以下代碼的結(jié)果是什么?

packagetest;

publicclassTestextendsBase{

publicstaticvoidmain(String[]args){

newTest().method();

}

publicvoidmethod(){

System.err.println(super.getClass().getName());

System.err.println(this.getClass().getSuperclass().getName());

}

}

classBase{

}

解答:第一個輸出test.Test、其次個輸出test.Base。super很簡單讓人以為也是調(diào)用了父類,實際上還是本類。

10、trueorfalse?

publicclassTest{

publicstaticvoidmain(String[]args){

Stringstr1=newString(abc);

Stringstr2=newString(abc);

System.err.println(str1.equals(str2));

StringBuffersb1=newStringBuffer(abc);

StringBuffersb2=newStringBuffer(abc);

System.err.println(sb1.equals(sb2));

}

}

解答:第一個true,其次個false。String重寫了Object中的equals方法,會將string拆分為字符數(shù)組,逐個比擬各個字符,代碼如下:

publicbooleanequals(ObjectanObject){

if(this==anObject){

returntrue;

}

if(anObjectinstanceofString){

StringanotherString=(String)anObject;

intn=value.length;

if(n==anotherString.value.length){

charv1[]=value;

charv2[]=anotherString.value;

inti=0;

while(n--!=0){

if(v1[i]!=v2[i])

returnfalse;

i++;

}

returntrue;

}

}

returnfalse;

}

Object中的equests方法如下:

publicbooleanequals(Objectobj){

return(this==obj);

}

11、輸出的結(jié)果是什么?

publicclassTest{

publicstaticvoidmain(String[]args){

System.err.println(newTest().method1());

System.err.println(newTest().method2());

}

publicintmethod1(){

intx=1;

try{

returnx;

}finally{

++x;

}

}

publicintmethod2(){

intx=1;

try{

returnx;

}finally{

return++x;

}

}

}

解答:第一個返回1,其次個返回2。finally中的代碼是肯定會被執(zhí)行的且在try中的代碼執(zhí)行完之后,因此若在其中return返回,會掩蓋掉try中的返回值。

假如這樣呢?

publicclassTest{

publicstaticvoidmain(String[]args){

System.err.println(method());

}

publicstaticbooleanmethod(){

try{

returntrue;

}finally{

returnfalse;

}

}

}

很明顯返回值應(yīng)當為false。

12、方法m1和m2有區(qū)分嗎?

解答:這里考察的是同步方法的問題。synchronized修飾方法時鎖定的是調(diào)用該方法的對象。它并不能使調(diào)用該方法的多個對象在執(zhí)行挨次上互斥,靜態(tài)修飾符很有必要。因此當不適用靜態(tài)時,創(chuàng)立多個對象執(zhí)行該方法,鎖都不一樣,還同步什么呢,因此用static修飾后才能實現(xiàn)想要的效果。

13、trueorfalse?

publicclassTest{

publicstaticvoidmain(String[]args){

Integeri1=127;

Integeri2=127;

System.err.println(i1==i2);

i1=128;

i2=128;

System.err.println(i1==i2);

}

}

解答:第一個為true,其次個為false。這個是對Integer包裝類型中應(yīng)用的享元模式的考察。

14、trueorfalse?

publicclassTest{

publicstaticvoidmain(String[]args){

Stringstr1=a;

Stringstr2=a;

Stringstr3=newString(a);

System.err.println(str1==str2);

System.err.println(str1==str3);

str3=ern();

System.err.println(str1==str3);

}

}

解答:這個是對StringPool的考察。答案為true、false、true

15、trueorfalse?

publicclassTest{

publicstaticvoidmain(String[]args){

System.err.println(12-11.9==0.1);

}

}

解答:結(jié)果為false。這個題我只說下我的想法,12-11.9進展運算后會轉(zhuǎn)換成對象,不在是根本數(shù)據(jù)類型,因此在進展恒等推斷時,就會是false。

16、以下代碼輸出是什么?

publicclassTest{

publicstaticvoidmain(String[]args){

BigIntegerone=newBigInteger(1);

BigIntegertwo=newBigInteger(2);

BigIntegerthree=newBigInteger(3);

BigIntegersum=newBigInteger(0);

sum.add(one);

sum.add(two);

sum.add(three);

System.out.println(sum.toString());

}

}

解答:這個是對大整數(shù)的考察。結(jié)果是不是6呢?看起來似乎沒毛病,其實不然。sum.add(one)與我們根本類型的sum+=one可不同,前者不會講結(jié)果賦值給sum對象,結(jié)果被賦值了這條語句的返回值。因此不管怎么add,sum對象的值是沒有變化的,因此結(jié)果為0。

18、如何迭代Map容器?__/

解答:0.

20、下面為一個單例的實現(xiàn)代碼,請指出代碼中有幾個錯誤或不合理之處,并改正。

publicclassTest{

publicTestinstance=null;

publicstaticTestgetInstance(){

if(instance==null){

instance=newTest();

returninstance;

}

}

}

解答:單例模式要滿意三點:1、私有化構(gòu)造方法;2、創(chuàng)立私有靜態(tài)對象;3、供應(yīng)公有靜態(tài)方法獵取唯一實例。

因此錯誤包含,1構(gòu)造函數(shù)沒有私有化,2對象非私有靜態(tài),3獵取實例的方法中return不應(yīng)包含在條件中。

java筆試簡答題及答案

1)什么是線程?

線程是操作系統(tǒng)能夠進展運算調(diào)度的最小單位,它被包含在進程之中,是進程中的實際運作單位。程序員可以通過它進展多處理器編程,你可以使用多線程對運算密集型任務(wù)提速。比方,假如一個線程完成一個任務(wù)要100毫秒,那么用十個線程完成改任務(wù)只需10毫秒。Java在語言層面對多線程供應(yīng)了卓越的支持,它也是一個很好的賣點。欲了解更多具體信息請點擊這里。

2)線程和進程有什么區(qū)分?

線程是進程的子集,一個進程可以有許多線程,每條線程并行執(zhí)行不同的任務(wù)。不同的進程使用不同的內(nèi)存空間,而全部的線程共享一片一樣的內(nèi)存空間。別把它和棧內(nèi)存搞混,每個線程都擁有單獨的棧內(nèi)存用來存儲本地數(shù)據(jù)。更多具體信息請點擊這里。

3)如何在Java中實現(xiàn)線程?

在語言層面有兩種方式。java.lang.Thread類的實例就是一個線程但是它需要調(diào)用java.lang.Runnable接口來執(zhí)行,由于線程類本身就是調(diào)用的Runnable接口所以你可以繼承java.lang.Thread類或者直接調(diào)用Runnable接口來重寫run()方法實現(xiàn)線程。更多具體信息請點擊這里.

4)用Runnable還是Thread?

這個問題是上題的后續(xù),大家都知道我們可以通過繼承Thread類或者調(diào)用Runnable接口來實現(xiàn)線程,問題是,那個方法更好呢?什么狀況下使用它?這個問題很簡單答復(fù),假如你知道Java不支持類的多重繼承,但允許你調(diào)用多個接口。所以假如你要繼承其他類,固然是調(diào)用Runnable接口好了。更多具體信息請點擊這里。

6)Thread類中的start()和run()方法有什么區(qū)分?

這個問題常常被問到,但還是能從今區(qū)分出面試者對Java線程模型的理解程度。start()方法被用來啟動新創(chuàng)立的線程,而且start()內(nèi)部調(diào)用了run()方法,這和直接調(diào)用run()方法的效果不一樣。當你調(diào)用run()方法的時候,只會是在原來的線程中調(diào)用,沒有新的線程啟動,start()方法才會啟動新線程。更多爭論請點擊這里

7)Java中Runnable和Callable有什么不同?

Runnable和Callable都代表那些要在不同的線程中執(zhí)行的任務(wù)。Runnable從JDK1.0開頭就有了,Callable是在JDK1.5增加的。它們的主要區(qū)分是Callable的call()方法可以返回值和拋出特別,而Runnable的run()方法沒有這些功能。Callable可以返回裝載有計算結(jié)果的Future對象。我的博客有更具體的說明。

8)Java中CyclicBarrier和CountDownLatch有什么不同?

CyclicBarrier和CountDownLatch都可以用來讓一組線程等待其它線程。與CyclicBarrier不同的是,CountdownLatch不能重新使用。點此查看更多信息和例如代碼。

9)Java內(nèi)存模型是什么?

Java內(nèi)存模型規(guī)定和指引Java程序在不同的內(nèi)存架構(gòu)、CPU和操作系統(tǒng)間有確定性地行為。它在多線程的狀況下尤其重要。Java內(nèi)存模型對一個線程所做的變動能被其它線程可見供應(yīng)了保證,它們之間是先行發(fā)生關(guān)x。這個關(guān)系定義了一些規(guī)章讓程序員在并發(fā)編程時思路更清楚。比方,先行發(fā)生關(guān)x確保了:

線程內(nèi)的代碼能夠按先后挨次執(zhí)行,這被稱為程序次序規(guī)章。

對于同一個鎖,一個解鎖操作肯定要發(fā)生在時間上后發(fā)生的另一個鎖定操作之前,也叫做管程鎖定規(guī)章。

前一個對volatile的寫操作在后一個volatile的讀操作之前,也叫volatile變量規(guī)章。

一個線程內(nèi)的任何操作必需在這個線程的start()調(diào)用之后,也叫作線程啟動規(guī)章。

一個線程的全部操作都會在線程終止之前,線程終止規(guī)章。

一個對象的終結(jié)操作必需在這個對象構(gòu)造完成之后,也叫對象終結(jié)規(guī)章。

可傳遞性

我劇烈建議大家閱讀《Java并發(fā)編程實踐》第十六章來加深對Java內(nèi)存模型的理解。

10)Java中的volatile變量是什么?

volatile是一個特別的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的狀況下,多線程對成員變量的操作對其它線程是透亮的。volatile變量可以保證下一個讀取操作會在前一個寫操作之后發(fā)生,就是上一題的volatile變量規(guī)章。點擊這里查看更多volatile的相關(guān)內(nèi)容。

11)什么是線程安全?Vector是一個線程安全類嗎?(詳見這里)

假如你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。假如每次運行結(jié)果和單線程運行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。一個線程安全的計數(shù)器類的同一個實例對象在被多個線程使用的狀況下也不會消失計算失誤。很明顯你可以將集合類分成兩組,線程安全和非線程安全的。Vector是用同步方法來實現(xiàn)線程安全的,而和它相像的ArrayList不是線程安全的。

12)Java中什么是競態(tài)條件?舉個例子說明。

競態(tài)條件會導(dǎo)致程序在并發(fā)狀況下消失一些bugs。多線程對一些資源的競爭的時候就會產(chǎn)生競態(tài)條件,假如首先要執(zhí)行的程序競爭失敗排到后面執(zhí)行了,那么整個程序就會消失一些不確定的bugs。這種bugs很難發(fā)覺而且會重復(fù)消失,由于線程間的隨機競爭。一個例子就是無序處理,詳見答案。

13)Java中如何停頓一個線程?

Java供應(yīng)了很豐富的API但沒有為停頓線程供應(yīng)API。JDK1.0原來有一些像stop(),suspend()和resume()的掌握方法但是由于潛在的死鎖威逼因此在后續(xù)的JDK版本中他們被棄用了,之后JavaAPI的設(shè)計者就沒有供應(yīng)一個兼容且線程安全的方法來停頓一個線程。當run()或者call()方法執(zhí)行完的時候線程會自動完畢,假如要手動完畢一個線程,你可以用volatile布爾變量來退出run()方法的循環(huán)或者是取消任務(wù)來中斷線程。點擊這里查看例如代碼。

14)一個線程運行時發(fā)生特別會怎樣?

這是我在一次面試中遇到的一個很刁鉆的Java面試題,簡潔的說,假如特別沒有被捕獲該線程將會停頓執(zhí)行。Thread.UncaughtExceptionHandler是用于處理未捕獲特別造成線程突然中斷狀況的一個內(nèi)嵌接口。當一個未捕獲特別將造成線程中斷的時候JVM會使用Thread.getUncaughtExceptionHandler()來查詢線程的UncaughtExceptionHandler并將線程和特別作為參數(shù)傳遞給handler的uncaughtException()方法進展處理。

15)如何在兩個線程間共享數(shù)據(jù)?

你可以通過共享對象來實現(xiàn)這個目的,或者是使用像堵塞隊列這樣并發(fā)的數(shù)據(jù)構(gòu)造。這篇教程《Java線程間通信》(涉及到在兩個線程間共享對象)用wait和notify方法實現(xiàn)了生產(chǎn)者消費者模型。

16)Java中notify和notifyAll有什么區(qū)分?

這又是一個刁鉆的問題,由于多線程可以等待單監(jiān)控鎖,JavaAPI的設(shè)計人員供應(yīng)了一些方法當?shù)却龡l件轉(zhuǎn)變的時候通知它們,但是這些方法沒有完全實現(xiàn)。notify()方法不能喚醒某個詳細的線程,所以只有一個線程在等待的時候它才有用武之地。而notifyAll()喚醒全部線程并允許他們爭奪鎖確保了至少有一個線程能連續(xù)運行。我的博客有更具體的資料和例如代碼。

17)為什么wait,notify和notifyAll這些方法不在thread類里面?

這是個設(shè)計相關(guān)的問題,它考察的是面試者對現(xiàn)有系統(tǒng)和一些普遍存在但看起來不合理的事物的看法。答復(fù)這些問題的時候,你要說明為什么把這些方法放在Object類里是有意義的,還有不把它放在Thread類里的緣由。一個很明顯的緣由是JAVA供應(yīng)的鎖是對象級的而不是線程級的,每個對象都有鎖,通過線程獲得。假如線程需要等待某些鎖那么調(diào)用對象中的wait()方法就有意義了。假如wait()方法定義在Thread類中,線程正在等待的是哪個鎖就不明顯了。簡潔的說,由于wait,notify和notifyAll都是鎖級別的操作,所以把他們定義在Object類中由于鎖屬于對象。你也可以查看這篇文章了解更多。

18)什么是ThreadLocal變量?

ThreadLocal是Java里一種特別的變量。每個線程都有一個ThreadLocal就是每個線程都擁有了自己獨立的一個變量,競爭條件被徹底消退了。它是為創(chuàng)立代價昂揚的對象獵取線程安全的好方法,比方你可以用ThreadLocal讓SimpleDateFormat變成線程安全的,由于那個類創(chuàng)立代價昂揚且每次調(diào)用都需要創(chuàng)立不同的實例所以不值得在局部范圍使用它,假如為每個線程供應(yīng)一個自己獨有的變量拷貝,將大大提高效率。首先,通過復(fù)用削減了代價昂揚的對象的創(chuàng)立個數(shù)。其次,你在沒有使用高代價的同步或者不變性的狀況下獲得了線程安全。線程局部變量的另一個不錯的例子是ThreadLocalRandom類,它在多線程環(huán)境中削減了創(chuàng)立代價昂揚的Random對象的個數(shù)。查看答案了解更多。

19)什么是FutureTask?

在Java并發(fā)程序中FutureTask表示一個可以取消的異步運算。它有啟動和取消運算、查詢運算是否完成和取回運算結(jié)果等方法。只有當運算完成的時候結(jié)果才能取回,假如運算尚未完成get方法將會堵塞。一個FutureTask對象可以對調(diào)用了Callable和Runnable的對象進展包裝,由于FutureTask也是調(diào)用了Runnable接口所以它可以提交給Executor來執(zhí)行。

20)Java中interrupted和isInterruptedd方法的區(qū)分?

interrupted()和isInterrupted()的.主要區(qū)分是前者會將中斷狀態(tài)去除而后者不會。Java多線程的中斷機制是用內(nèi)部標識來實現(xiàn)的,調(diào)用Terrupt()來中斷一個線程就會設(shè)置中斷標識為true。當中斷線程調(diào)用靜態(tài)方法Terrupted()來檢查中斷狀態(tài)時,中斷狀態(tài)會被清零。而非靜態(tài)方法isInterrupted()用來查詢其它線程的中斷狀態(tài)且不會轉(zhuǎn)變中斷狀態(tài)標識。簡潔的說就是任何拋出InterruptedException特別的方法都會將中斷狀態(tài)清零。無論如何,一個線程的中斷狀態(tài)有有可能被其它線程調(diào)用中斷來轉(zhuǎn)變。

21)為什么wait和notify方法要在同步塊中調(diào)用?

主要是由于JavaAPI強制要求這樣做,假如你不這么做,你的代碼會拋出IllegalMonitorStateException特別。還有一個緣由是為了避開wait和notify之間產(chǎn)生競態(tài)條件。

22)為什么你應(yīng)當在循環(huán)中檢查等待條件?

處于等待狀態(tài)的線程可能會收到錯誤警報和偽喚醒,假如不在循環(huán)中檢查等待條件,程序就會在沒有滿意完畢條件的狀況下退出。因此,當一個等待線程醒來時,不能認為它原來的等待狀態(tài)仍舊是有效的,在notify()方法調(diào)用之后和等待線程醒來之前這段時間它可能會轉(zhuǎn)變。這就是在循環(huán)中使用wait()方法效果更好的緣由,你可以在Eclipse中創(chuàng)立模板調(diào)用wait和notify試一試。假如你想了解更多關(guān)于這個問題的內(nèi)容,我推舉你閱讀《EffectiveJava》這本書中的線程和同步章節(jié)。

23)Java中的同步集合與并發(fā)集合有什么區(qū)分?

同步集合與并發(fā)集合都為多線程和并發(fā)供應(yīng)了適宜的線程安全的集合,不過并發(fā)集合的可擴展性更高。在Java1.5之前程序員們只有同步集合來用且在多線程并發(fā)的時候會導(dǎo)致爭用,阻礙了系統(tǒng)的擴展性。Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅供應(yīng)線程安全還用鎖分別和內(nèi)局部區(qū)等現(xiàn)代技術(shù)提高了可擴展性。更多內(nèi)容詳見答案。

24)Java中堆和棧有什么不同?

為什么把這個問題歸類在多線程和并發(fā)面試題里?由于棧是一塊和線程嚴密相關(guān)的內(nèi)存區(qū)域。每個線程都有自己的棧內(nèi)存,用于存儲本地變量,方法參數(shù)和棧調(diào)用,一個線程中存儲的變量對其它線程是不行見的。而堆是全部線程共享的一片公用內(nèi)存區(qū)域。對象都在堆里創(chuàng)立,為了提升效率線程會從堆中弄一個緩存到自己的棧,假如多個線程使用該變量就可能引發(fā)問題,這時volatile變量就可以發(fā)揮作用了,它要求線程從主存中讀取變量的值。

25)什么是線程池?為什么要使用它?

創(chuàng)立線程要花費昂貴的資源和時間,假如任務(wù)來了才創(chuàng)立線程那么響應(yīng)時間會變長,而且一個進程能創(chuàng)立的線程數(shù)有限。為了避開這些問題,在程序啟動的時候就創(chuàng)立若干線程來響應(yīng)處理,它們被稱為線程池,里面的線程叫工作線程。從JDK1.5開頭,JavaAPI供應(yīng)了Executor框架讓你可以創(chuàng)立不同的線程池。比方單線程池,每次處理一個任務(wù);數(shù)目固定的線程池或者是緩存線程池(一個適合許多生存期短的任務(wù)的程序的可擴展線程池)。更多內(nèi)容詳見這篇文章。

26)如何寫代碼來解決生產(chǎn)者消費者問題?

在現(xiàn)實中你解決的很多線程問題都屬于生產(chǎn)者消費者模型,就是一個線程生產(chǎn)任務(wù)供其它線程進展消費,你必需知道怎么進展線程間通信來解決這個問題。比擬低級的方法是用wait和notify來解決這個問題,比擬贊的方法是用Semaphore或者BlockingQueue來實現(xiàn)生產(chǎn)者消費者模型,這篇教程有實現(xiàn)它。

27)如何避開死鎖?

Java多線程中的死鎖

死鎖是指兩個或兩個以上的進程在執(zhí)行過程中,因爭奪資源而造成的一種相互等待的現(xiàn)象,若無外力作用,它們都將無法推動下去。這是一個嚴峻的問題,由于死鎖會讓你的程序掛起無法完成任務(wù),死鎖的發(fā)生必需滿意以下四個條件:

互斥條件:一個資源每次只能被一個進程使用。

懇求與保持條件:一個進程因懇求資源而堵塞時,對已獲得的資源保持不放。

不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。

循環(huán)等待條件:若干進程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

避開死鎖最簡潔的方法就是阻擋循環(huán)等待條件,將系統(tǒng)中全部的資源設(shè)置標志位、排序,規(guī)定全部的進程申請資源必需以肯定的挨次(升序或降序)做操作來避開死鎖。這篇教程有代碼例如和避開死鎖的爭論細節(jié)。

28)Java中活鎖和死鎖有什么區(qū)分?

這是上題的擴展,活鎖和死鎖類似,不同之處在于處于活鎖的線程或進程的狀態(tài)是不斷轉(zhuǎn)變的,活鎖可以認為是一種特別的饑餓。一個現(xiàn)實的活鎖例子是兩個人在狹小的走廊遇到,兩個人都試著避讓對方好讓彼此通過,但是由于避讓的方向都一樣導(dǎo)致最終誰都不能通過走廊。簡潔的說就是,活鎖和死鎖的主要區(qū)分是前者進程的狀態(tài)可以轉(zhuǎn)變但是卻不能連續(xù)執(zhí)行。

29)怎么檢測一個線程是否擁有鎖?

我始終不知道我們竟然可以檢測一個線程是否擁有鎖,直到我參與了一次電話面試。在java.lang.Thread中有一個方法叫holdsLock(),它返回true假如當且僅當當前線程擁有某個詳細對象的鎖。你可以查看這篇文章了解更多。

30)你如何在Java中獵取線程堆棧?

對于不同的操作系統(tǒng),有多種方法來獲得Java進程的線程堆棧。當你獵取線程堆棧時,JVM會把全部線程的狀態(tài)存到日志文件或者輸出到掌握臺。在Windows你可以使用Ctrl+Break組合鍵來獵取線程堆棧,Linux下用kill-3命令。你也可以用jstack這個工具來獵取,它對線程id進展操作,你可以用jps這個工具找到id。

31)JVM中哪個參數(shù)是用來掌握線程的棧堆棧小的

這個問題很簡潔,-Xss參數(shù)用來掌握線程的堆棧大小。你可以查看JVM配置列表來了解這個參數(shù)的更多信息。

32)Java中synchronized和ReentrantLock有什么不同?

Java在過去很長一段時間只能通過synchronized關(guān)鍵字來實現(xiàn)互斥,它有一些缺點。比方你不能擴展鎖之外的方法或者塊邊界,嘗試獵取鎖時不能中途取消等。Java5通過Lock接口供應(yīng)了更簡單的掌握來解決這些問題。

ReentrantLock類實現(xiàn)了Lock,它擁有與synchronized一樣的并發(fā)性和內(nèi)存語義且它還具有可擴展性。你可以查看這篇文章了解更多

33)有三個線程T1,T2,T3,怎么確保它們按挨次執(zhí)行?

在多線程中有多種方法讓線程按特定挨次執(zhí)行,你可以用線程類的join()方法在一個線程中啟動另一個線程,另外一個線程完成該線程連續(xù)執(zhí)行。為了確保三個線程的挨次你應(yīng)當先啟動最終一個(T3調(diào)用T2,T2調(diào)用T1),這樣T1就會先完成而T3最終完成。你可以查看這篇文章了解更多。

34)Thread類中的yield方法有什么作用?

Yield方法可以暫停當前正在執(zhí)行的線程對象,讓其它有一樣優(yōu)先級的線程執(zhí)行。它是一個靜態(tài)方法而且只保證當前線程放棄CPU占用而不能保證使其它線程肯定能占用CPU,執(zhí)行yield()的線程有可能在進入到暫停狀態(tài)后立刻又被執(zhí)行。點擊這里查看更多yield方法的相關(guān)內(nèi)容。

35)Java中ConcurrentHashMap的并發(fā)度是什么?

ConcurrentHashMap把實際map劃分成若干局部來實現(xiàn)它的可擴展性和線程安全。這種劃分是使用并發(fā)度獲得的,它是ConcurrentHashMap類構(gòu)造函數(shù)的一個可選參數(shù),默認值為16,這樣在多線程狀況下就能避開爭用。欲了解更多并發(fā)度和內(nèi)部大小調(diào)整請閱讀我的文章HowConcurrentHashMapworksinJava。

36)Java中Semaphore是什么?

Java中的Semaphore是一種新的同步類,它是一個計數(shù)信號。從概念上講,從概念上講,信號量維護了一個許可集合。如有必要,在許可可用前會堵塞每一個acquire(),然后再獵取該許可。每個release()添加一個許可,從而可能釋放一個正在堵塞的獵取者。但是,不使用實際的許可對象,Semaphore只對可用許可的號碼進展計數(shù),并實行相應(yīng)的行動。信號量經(jīng)常用于多線程的代碼中,比方數(shù)據(jù)庫連接池。更多具體信息請點擊這里。

37)假如你提交任務(wù)時,線程池隊列已滿。會時發(fā)會生什么?

這個問題問得很狡猾,很多程序員會認為該任務(wù)會堵塞直到線程池隊列有空位。事實上假如一個任務(wù)不能被調(diào)度執(zhí)行那么ThreadPoolExecutor’ssubmit()方法將會拋出一個RejectedExecutionException特別。

38)Java線程池中submit()和execute()方法有什么區(qū)分?

兩個方法都可以向線程池提交任務(wù),execute()方法的返回類型是void,它定義在Executor接口中,而submit()方法可以返回持有計算結(jié)果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。更多具體信息請點擊這里。

39)什么是堵塞式方法?

堵塞式方法是指程序會始終等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是始終等待客戶端連接。這里的堵塞是指調(diào)用結(jié)果返回之前,當前線程會被掛起,直到得到結(jié)果之后才會返回。此外,還有異步和非堵塞式方法在任務(wù)完成前就返回。更多具體信息請點擊這里。

40)Swing是線程安全的嗎?為什么?

你可以很確定的給出答復(fù),Swing不是線程安全的,但是你應(yīng)當解釋這么答復(fù)的緣由即便面試官沒有問你為什么。當我們說swing不是線程安全的經(jīng)常提到它的組件,這些組件不能在多線程中進展修改,全部對GUI組件的更新都要在AWT線程中完成,而Swing供應(yīng)了同步和異步兩種回調(diào)方法來進展更新。點擊這里查看更多swing和線程安全的相關(guān)內(nèi)容。

41)Java中invokeAndWait和invokeLater有什么區(qū)分?

這兩個方法是SwingAPI供應(yīng)給Java開發(fā)者用來從當前線程而不是大事派發(fā)線程更新GUI組件用的。InvokeAndWait()同步更新GUI組件,比方一個進度條,一旦進度更新了,進度條也要做出相應(yīng)轉(zhuǎn)變。假如進度被多個線程跟蹤,那么就調(diào)用invokeAndWait()方法懇求大事派發(fā)線程對組件進展相應(yīng)更新。而invokeLater()方法是異步調(diào)用更新組件的。更多具體信息請點擊這里。

42)SwingAPI中那些方法是線程安全的?

這個問題又提到了swing和線程安全,雖然組件不是線程安全的但是有一些方法是可以被多線程安全調(diào)用的,比方repaint(),revalidate()。

JTextComponent的setText()方法和JTextArea的()和append()方法也是線程安全的。

43)如何在Java中創(chuàng)立Immutable對象?

這個問題看起來和多線程沒什么關(guān)系,但不變性有助于簡化已經(jīng)很簡單的并發(fā)程序。Immutable對象可以在沒有同步的狀況下共享,降低了對該對象進展并發(fā)訪問時的同步化開銷??墒荍ava沒有@Immutable這個注解符,要創(chuàng)立不行變類,要實現(xiàn)下面幾個步驟:通過構(gòu)造方法初始化全部成員、對變量不要供應(yīng)setter方法、將全部的成員聲明為私有的,這樣就不允許直接訪問這些成員、在getter方法中,不要直接返回對象本身,而是克隆對象,并返回對象的拷貝。我的文章howtomakeanobjectImmutableinJava有具體的教程,看完你可以布滿自信。

44)Java中的ReadWriteLock是什么?

一般而言,讀寫鎖是用來提升并發(fā)程序性能的鎖分別技術(shù)的成果。Java中的ReadWriteLock是Java5中新增的一個接口,一個ReadWriteLock維護一對關(guān)聯(lián)的鎖,一個用于只讀操作一個用于寫。在沒有寫線程的狀況下一個讀鎖可能會同時被多個讀線程持有。寫鎖是獨占的,你可以使用JDK中的ReentrantReadWriteLock來實現(xiàn)這個規(guī)章,它最多支持65535個寫鎖和65535個讀鎖。

45)多線程中的忙循環(huán)是什么?

忙循環(huán)就是程序員用循環(huán)讓一個線程等待,不像傳統(tǒng)方法wait(),sleep()或yield()它們都放棄了CPU掌握,而忙循環(huán)不會放棄CPU,它就是在運行一個空循環(huán)。這么做的目的是為了保存CPU緩存,在多核系統(tǒng)中,一個等待線程醒來的時候可能會在另一個內(nèi)核運行,這樣會重建緩存。為了避開重建緩存和削減等待重建的時間就可以使用它了。你可以查看這篇文章獲得更多信息。

46)volatile變量和atomic變量有什么不同?

這是個好玩的問題。首先,volatile變量和atomic變量看起來很像,但功能卻不一樣。Volatile變量可以確保先行關(guān)系,即寫操作會發(fā)生在后續(xù)的讀操作之前,但它并不能保證原子性。例如用volatile修飾count變量那么count++操作就不是原子性的。而AtomicInteger類供應(yīng)的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進展增量操作把當前值加一,其它數(shù)據(jù)類型和引用變量也可以進展相像操作。

47)假如同步塊內(nèi)的線程拋出特別會發(fā)生什么?

這個問題坑了許多Java程序員,若你能想到鎖是否釋放這條線索來答復(fù)還有點盼望答對。無論你的同步塊是正常還是特別退出的,里面的線程都會釋放鎖,所以比照鎖接口我更喜愛同步塊,由于它不用我花費精力去釋放鎖,該功能可以在finallyblock里釋放鎖實現(xiàn)。

48)單例模式的雙檢鎖是什么?

這個問題在Java面試中常常被問到,但是面試官對答復(fù)此問題的滿足度僅為50%。一半的人寫不出雙檢鎖還有一半的人說不出它的隱患和Java1.5是如何對它修正的。它其實是一個用來創(chuàng)立線程安全的單例的老方法,當單例實例第一次被創(chuàng)立時它試圖用單個鎖進展性能優(yōu)化,但是由于太過于簡單在JDK1.4中它是失敗的,我個人也不喜愛它。無論如何,即便你也不喜愛它但是還是要了解一下,由于它常常被問到。你可以查看howdoublecheckedlockingonSingletonworks這篇文章獲得更多信息。

49)如何在Java中創(chuàng)立線程安全的Singleton?

這是上面那個問題的后續(xù),假如你不喜愛雙檢鎖而面試官問了創(chuàng)立Singleton類的替代方法,你可以利用JVM的類加載和靜態(tài)變量初始化特征來創(chuàng)立Singleton實例,或者是利用枚舉類型來創(chuàng)立Singleton,我很喜愛用這種方法。你可以查看這篇文章獲得更多信息。

50)寫出3條你遵循的多線程最正確實踐

這種問題我最喜愛了,我信任你在寫并發(fā)代碼來提升性能的時候也會遵循某些最正確實踐。以下三條最正確實踐我覺得大多數(shù)Java程序員都應(yīng)當遵循:

給你的線程起個有意義的名字。

這樣可以便利找bug或追蹤。O

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論