更新時間:2020-11-16 17:29:01 來源:動力節點 瀏覽1491次
多線程系列一直是Java面試題中的經典,多線程(multithreading),是指從軟件或者硬件上實現多個線程并發執行的技術,是我們學習Java技術的必學課程之一。本文我們就根據以往的資料和前輩們的面試經驗來總結一下必看多線程面試題。
1. 線程和進程的區別?
·性質不同
進程(Process)是計算機中的程序關于某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。
線程(英語:thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。
·適用范圍不同
使用進程目的在于清晰地刻畫動態系統的內在規律,有效管理和調度進入計算機系統主存儲器運行的程序。
線程為操作系統內核調度的內核線程,如Win32線程;由用戶進程自行調度的用戶線程,如Linux平臺的POSIX Thread;或者由內核與用戶進程,如Windows 7的線程,進行混合調度。
2.設計四個線程,其中兩個線程每次對變量i加1,另外兩個線程每次對i減1.
package com.wang.reflect;
/**
* 設計四個線程,其中兩個線程每次對變量i加1,另外兩個線程每次對i減1.
* @author Administrator
*
*/
public class Demo02 {
private int i=0;
public static void main(String[] args) {
Demo02 demo=new Demo02();
Add add = demo.new Add();
Sub sub = demo.new Sub();
for(int i=1;i<=2;i++){
new Thread(add,"線程"+i).start();
new Thread(sub,"線程"+i).start();
}
}
//定義一個內部類Add,實現功能每次對i加一
class Add implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
addOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//定義一個內部類Sub,實現功能每次對i減1
class Sub implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
subOne();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void addOne() {
i++;
System.out.println(Thread.currentThread().getName()+"加一的值為:"+i);
}
public synchronized void subOne(){
i--;
System.out.println(Thread.currentThread().getName()+"減一的值為:"+i);
}
}
3.volatile關鍵字的作用
一個非常重要的問題,是每個學習、應用多線程的Java程序員都必須掌握的。理解volatile關鍵字的作用的前提是要理解Java內存模型,這里就不講Java內存模型了,可以參見第31點,volatile關鍵字的作用主要有兩個:
(1)多線程主要圍繞可見性和原子性兩個特性而展開,使用volatile關鍵字修飾的變量,保證了其在多線程之間的可見性,即每次讀取到volatile變量,一定是最新的數據
(2)代碼底層執行不像我們看到的高級語言—-Java程序這么簡單,它的執行是Java代碼–>字節碼–>根據字節碼執行對應的C/C++代碼–>C/C++代碼被編譯成匯編語言–>和硬件電路交互,現實中,為了獲取更好的性能JVM可能會對指令進行重排序,多線程下可能會出現一些意想不到的問題。使用volatile則會對禁止語義重排序,當然這也一定程度上降低了代碼執行效率
從實踐角度而言,volatile的一個重要作用就是和CAS結合,保證了原子性,詳細的可以參見java.util.concurrent.atomic包下的類,比如AtomicInteger。
4. 創建線程有哪幾種方式?
創建線程有三種方式:
·繼承 Thread 重寫 run 方法;
·實現 Runnable 接口;
·實現 Callable 接口。
5. 線程有哪些狀態?
線程的狀態:
·NEW 尚未啟動
·RUNNABLE 正在執行中
·BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
·WAITING 永久等待狀態
·TIMED_WAITING 等待指定的時間重新被喚醒的狀態
·TERMINATED 執行完成
6. sleep() 和 wait() 有什么區別?
·類的不同:sleep() 來自 Thread,wait() 來自 Object。
·釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
·用法不同:sleep() 時間到會自動恢復;wait() 可以使用 notify()/notifyAll()直接喚醒。
7. 在 Java 程序中怎么保證多線程的運行安全?
方法一:使用安全類,比如 Java. util. concurrent 下的類。
方法二:使用自動鎖 synchronized。
方法三:使用手動鎖 Lock。
手動鎖 Java 示例代碼如下:
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println("獲得鎖");
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println("釋放鎖");
lock. unlock();
}
8. synchronized 和 volatile 的區別是什么?
·volatile 是變量修飾符;synchronized 是修飾類、方法、代碼段。
·volatile 僅能實現變量的修改可見性,不能保證原子性;而 synchronized 則可以保證變量的修改可見性和原子性。
·volatile 不會造成線程的阻塞;synchronized 可能會造成線程的阻塞。
9. 為什么要使用多線程
·使用線程可以把占據時間長的程序中的任務放到后臺去處理。
·用戶界面更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某件事件的處理,可以彈出一個
·進度條來顯示處理的進度。
·程序的運行效率可能會提高。
·在一些等待的任務實現上如用戶輸入,文件讀取和網絡收發數據等,線程就比較有用了。
10、如何在兩個線程之間共享數據
通過在線程之間共享對象就可以了,然后通過wait/notify/notifyAll、await/signal/signalAll進行喚起和等待,比方說阻塞隊列BlockingQueue就是為線程之間共享數據而設計的。
多線程作為目前的主流Java技術之一,一直以來備受關注,也是我們參加各大公司的必考知識點之一。有了上面的10道必看的多線程面試題,小伙伴們可以以此為基礎拓展自己的多線程知識,全面溫習多線程的各個知識點,全面學習更多的java面試題,在面試中爭取突破自我,取得最好的成績!
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習