學(xué)習(xí)啦 > 創(chuàng)業(yè)指南 > 職場(chǎng) > 面試題 > Java程序員面試中的多線(xiàn)程問(wèn)題

Java程序員面試中的多線(xiàn)程問(wèn)題

時(shí)間: 護(hù)托1061 分享

Java程序員面試中的多線(xiàn)程問(wèn)題

  很多核心Java面試題來(lái)源于多線(xiàn)程(Multi-Threading)和集合框架(Collections Framework),理解核心線(xiàn)程概念時(shí),嫻熟的實(shí)際經(jīng)驗(yàn)是必需的。下面就由學(xué)習(xí)啦小編為大家介紹一下Java程序員面試中的多線(xiàn)程問(wèn)題的文章,歡迎閱讀。

  Java程序員面試中的多線(xiàn)程問(wèn)題篇1

  1、Java中多線(xiàn)程同步是什么?

  在多線(xiàn)程程序下,同步能控制對(duì)共享資源的訪(fǎng)問(wèn)。如果沒(méi)有同步,當(dāng)一個(gè)Java線(xiàn)程在修改一個(gè)共享變量時(shí),另外一個(gè)線(xiàn)程正在使用或者更新同一個(gè)變量,這樣容易導(dǎo)致程序出現(xiàn)錯(cuò)誤的結(jié)果。

  2、解釋實(shí)現(xiàn)多線(xiàn)程的幾種方法?

  一Java線(xiàn)程可以實(shí)現(xiàn)Runnable接口或者繼承Thread類(lèi)來(lái)實(shí)現(xiàn),當(dāng)你打算多重繼承時(shí),優(yōu)先選擇實(shí)現(xiàn)Runnable。

  3、Thread.start()與Thread.run()有什么區(qū)別?

  Thread.start()方法(native)啟動(dòng)線(xiàn)程,使之進(jìn)入就緒狀態(tài),當(dāng)cpu分配時(shí)間該線(xiàn)程時(shí),由JVM調(diào)度執(zhí)行run()方法。

  Java程序員面試中的多線(xiàn)程問(wèn)題篇2

  1、為什么需要run()和start()方法,我們可以只用run()方法來(lái)完成任務(wù)嗎?

  我們需要run()&start()這兩個(gè)方法是因?yàn)镴VM創(chuàng)建一個(gè)單獨(dú)的線(xiàn)程不同于普通方法的調(diào)用,所以這項(xiàng)工作由線(xiàn)程的start方法來(lái)完成,start由本地方法實(shí)現(xiàn),需要顯示地被調(diào)用,使用這倆個(gè)方法的另外一個(gè)好處是任何一個(gè)對(duì)象都可以作為線(xiàn)程運(yùn)行,只要實(shí)現(xiàn)了Runnable接口,這就避免因繼承了Thread類(lèi)而造成的Java的多繼承問(wèn)題。

  2、什么是ThreadLocal類(lèi),怎么使用它?

  ThreadLocal是一個(gè)線(xiàn)程級(jí)別的局部變量,并非“本地線(xiàn)程”。ThreadLocal為每個(gè)使用該變量的線(xiàn)程提供了一個(gè)獨(dú)立的變量副本,每個(gè)線(xiàn)程修改副本時(shí)不影響其它線(xiàn)程對(duì)象的副本(譯者注)。

  下面是線(xiàn)程局部變量(ThreadLocal variables)的關(guān)鍵點(diǎn):

  一個(gè)線(xiàn)程局部變量(ThreadLocal variables)為每個(gè)線(xiàn)程方便地提供了一個(gè)單獨(dú)的變量。

  ThreadLocal實(shí)例通常作為靜態(tài)的私有的(private static)字段出現(xiàn)在一個(gè)類(lèi)中,這個(gè)類(lèi)用來(lái)關(guān)聯(lián)一個(gè)線(xiàn)程。

  當(dāng)多個(gè)線(xiàn)程訪(fǎng)問(wèn)ThreadLocal實(shí)例時(shí),每個(gè)線(xiàn)程維護(hù)ThreadLocal提供的獨(dú)立的變量副本。

  常用的使用可在DAO模式中見(jiàn)到,當(dāng)DAO類(lèi)作為一個(gè)單例類(lèi)時(shí),數(shù)據(jù)庫(kù)鏈接(connection)被每一個(gè)線(xiàn)程獨(dú)立的維護(hù),互不影響。(基于線(xiàn)程的單例)

  Java程序員面試中的多線(xiàn)程問(wèn)題篇3

  1、什么時(shí)候拋出InvalidMonitorStateException異常,為什么?

  調(diào)用wait()/notify()/notifyAll()中的任何一個(gè)方法時(shí),如果當(dāng)前線(xiàn)程沒(méi)有獲得該對(duì)象的鎖,那么就會(huì)拋出IllegalMonitorStateException的異常(也就是說(shuō)程序在沒(méi)有執(zhí)行對(duì)象的任何同步塊或者同步方法時(shí),仍然嘗試調(diào)用wait()/notify()/notifyAll()時(shí))。由于該異常是RuntimeExcpetion的子類(lèi),所以該異常不一定要捕獲(盡管你可以捕獲只要你愿意).作為RuntimeException,此類(lèi)異常不會(huì)在wait(),notify(),notifyAll()的方法簽名提及。

  2、Sleep()、suspend()和wait()之間有什么區(qū)別?

  Thread.sleep()使當(dāng)前線(xiàn)程在指定的時(shí)間處于“非運(yùn)行”(Not Runnable)狀態(tài)。線(xiàn)程一直持有對(duì)象的監(jiān)視器。比如一個(gè)線(xiàn)程當(dāng)前在一個(gè)同步塊或同步方法中,其它線(xiàn)程不能進(jìn)入該塊或方法中。如果另一線(xiàn)程調(diào)用了interrupt()方法,它將喚醒那個(gè)“睡眠的”線(xiàn)程。

  注意:sleep()是一個(gè)靜態(tài)方法。這意味著只對(duì)當(dāng)前線(xiàn)程有效,一個(gè)常見(jiàn)的錯(cuò)誤是調(diào)用t.sleep(),(這里的t是一個(gè)不同于當(dāng)前線(xiàn)程的線(xiàn)程)。即便是執(zhí)行t.sleep(),也是當(dāng)前線(xiàn)程進(jìn)入睡眠,而不是t線(xiàn)程。t.suspend()是過(guò)時(shí)的方法,使用suspend()導(dǎo)致線(xiàn)程進(jìn)入停滯狀態(tài),該線(xiàn)程會(huì)一直持有對(duì)象的監(jiān)視器,suspend()容易引起死鎖問(wèn)題。

  object.wait()使當(dāng)前線(xiàn)程出于“不可運(yùn)行”狀態(tài),和sleep()不同的是wait是object的方法而不是thread。調(diào)用object.wait()時(shí),線(xiàn)程先要獲取這個(gè)對(duì)象的對(duì)象鎖,當(dāng)前線(xiàn)程必須在鎖對(duì)象保持同步,把當(dāng)前線(xiàn)程添加到等待隊(duì)列中,隨后另一線(xiàn)程可以同步同一個(gè)對(duì)象鎖來(lái)調(diào)用object.notify(),這樣將喚醒原來(lái)等待中的線(xiàn)程,然后釋放該鎖?;旧蟱ait()/notify()與sleep()/interrupt()類(lèi)似,只是前者需要獲取對(duì)象鎖。

  3、在靜態(tài)方法上使用同步時(shí)會(huì)發(fā)生什么事?

  同步靜態(tài)方法時(shí)會(huì)獲取該類(lèi)的“Class”對(duì)象,所以當(dāng)一個(gè)線(xiàn)程進(jìn)入同步的靜態(tài)方法中時(shí),線(xiàn)程監(jiān)視器獲取類(lèi)本身的對(duì)象鎖,其它線(xiàn)程不能進(jìn)入這個(gè)類(lèi)的任何靜態(tài)同步方法。它不像實(shí)例方法,因?yàn)槎鄠€(gè)線(xiàn)程可以同時(shí)訪(fǎng)問(wèn)不同實(shí)例同步實(shí)例方法。

  4、當(dāng)一個(gè)同步方法已經(jīng)執(zhí)行,線(xiàn)程能夠調(diào)用對(duì)象上的非同步實(shí)例方法嗎?

  可以,一個(gè)非同步方法總是可以被調(diào)用而不會(huì)有任何問(wèn)題。實(shí)際上,Java沒(méi)有為非同步方法做任何檢查,鎖對(duì)象僅僅在同步方法或者同步代碼塊中檢查。如果一個(gè)方法沒(méi)有聲明為同步,即使你在使用共享數(shù)據(jù)Java照樣會(huì)調(diào)用,而不會(huì)做檢查是否安全,所以在這種情況下要特別小心。一個(gè)方法是否聲明為同步取決于臨界區(qū)訪(fǎng)問(wèn)(critial section access),如果方法不訪(fǎng)問(wèn)臨界區(qū)(共享資源或者數(shù)據(jù)結(jié)構(gòu))就沒(méi)必要聲明為同步的。

  下面有一個(gè)示例說(shuō)明:Common類(lèi)有兩個(gè)方法synchronizedMethod1()和method1(),MyThread類(lèi)在獨(dú)立的線(xiàn)程中調(diào)用這兩個(gè)方法。

  Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Common {
 
public synchronized void synchronizedMethod1() {
System.out.println("synchronizedMethod1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedMethod1 done");
}
public void method1() {
System.out.println("Method 1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 done");
}
}

  Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MyThread extends Thread {
private int id = 0;
private Common common;
 
public MyThread(String name, int no, Common object) {
super(name);
common = object;
id = no;
}
 
public void run() {
System.out.println("Running Thread" + this.getName());
try {
if (id == 0) {
common.synchronizedMethod1();
} else {
common.method1();
}
} catch (Exception e) {
e.printStackTrace();
}
}
 
public static void main(String[] args) {
Common c = new Common();
MyThread t1 = new MyThread("MyThread-1", 0, c);
MyThread t2 = new MyThread("MyThread-2", 1, c);
t1.start();
t2.start();
}
}

  Java

1
 

  這里是程序的輸出:

  Java

1
2
3
4
5
6
Running ThreadMyThread-1
synchronizedMethod1 called
Running ThreadMyThread-2
Method 1 called
synchronizedMethod1 done
Method 1 done

  結(jié)果表明即使synchronizedMethod1()方法執(zhí)行了,method1()也會(huì)被調(diào)用。

3150429