Java常見面試題總結(八)
本次的面試題:多執行緒知識的面試解答題。
1. 有T1、T2、T3三個執行緒,如何怎樣保證T2在T1執行完後執行,T3在T2執行完後執行?
答:使用join方法。
join方法的功能是使非同步執行的執行緒變成同步執行。即呼叫執行緒例項的start方法後,該方法會立即返回,如果呼叫start方法後,需要使用一個由這個執行緒計算得到的值,就必須使用join方法。如果不使用join方法,就不能保證當執行到start方法後面的某條語句時,這個執行緒一定會執行完。而使用join方法後,直到這個執行緒退出,程式才會往下執行。
2.Java中的Lock介面,比起synchronized,優勢在哪裡?
如果需要實現一個高效的快取,它允許多個使用者讀,但只允許一個使用者寫,以此來保持它的完整性,如何實現?
Lock介面最大的優勢是為讀和寫分別提供了鎖。
讀寫鎖ReadWriteLock擁有更加強大的功能,它可細分為讀鎖和解鎖。
讀鎖可以允許多個進行讀操作的執行緒同時進入,但不允許寫程序進入;寫鎖只允許一個寫程序進入,在這期間任何程序都不能再進入。(完全符合題目中允許多個使用者讀和一個使用者寫的條件)
要注意的是每個讀寫鎖都有掛鎖和解鎖,最好將每一對掛鎖和解鎖操作都用try、finally來套入中間的程式碼,這樣就會防止因異常的發生而造成死鎖得情況。
下面是一個示例程式:
```
import java.util.Random;
import java.util.concurrent.locks.*;
public class ReadWriteLockTest {
public static void main(String[] args) {
final TheData myData=new TheData(); //這是各執行緒的共享資料
for(int i=0;i<3;i++){ //開啟3個讀執行緒
new Thread(new Runnable(){
@Override
public void run() {
while(true){
myData.get();
}
}
}).start();
}
for(int i=0;i<3;i++){ //開啟3個寫執行緒
new Thread(new Runnable(){
@Override
public void run() {
while(true){
myData.put(new Random().nextInt(10000));
}
}
}).start();
}
}
}
class TheData{
private Object data=null;
private ReadWriteLock rwl=new ReentrantReadWriteLock();
public void get(){
rwl.readLock().lock(); //讀鎖開啟,讀執行緒均可進入
try { //用try finally來防止因異常而造成的死鎖
System.out.println(Thread.currentThread().getName()+"is ready to read");
Thread.sleep(new Random().nextInt(100));
System.out.println(Thread.currentThread().getName()+"have read date"+data);
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
rwl.readLock().unlock(); //讀鎖解鎖
}
}
public void put(Object data){
rwl.writeLock().lock(); //寫鎖開啟,這時只有一個寫執行緒進入
try {
System.out.println(Thread.currentThread().getName()+"is ready to write");
Thread.sleep(new Random().nextInt(100));
this.data=data;
System.out.println(Thread.currentThread().getName()+"have write date"+data);
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
rwl.writeLock().unlock(); //寫鎖解鎖
}
}
}
```
3. java中wait和sleep方法有何不同?
很大的不同是在等待時wait會釋放鎖,而sleep一直持有鎖。Wait通常被用於執行緒間互動,sleep通常被用於暫停執行。
其它不同有:
- sleep是Thread類的靜態方法,wait是Object方法。
- wait,notify和notifyAll只能在同步控制方法或者同步控制塊裡面使用,而sleep可以在任何地方使用
- sleep必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常。