1. 程式人生 > >面試題:執行緒是什麼?多執行緒

面試題:執行緒是什麼?多執行緒

執行緒在面試中已經是常客了,也是我們必備的知識點,關於執行緒,問的最多的便是執行緒是什麼?為什麼使用多執行緒?多執行緒的示例以及解決方案?執行緒池是什麼?

一.執行緒是什麼?

Thread類中有這樣的明確定義:執行緒是程式中執行的執行緒,Java虛擬機器允許程式同時執行多個執行執行緒。

具有較高優先順序的執行緒優先於優先順序較低的執行緒執行,每個執行緒可能也可能不會被標記為守護程序。當在某個執行緒中執行建立一個新的 Thread物件時,新的執行緒的優先順序最初設定為等於建立執行緒的優先順序,並且當且僅當建立執行緒是守護程序時才是守護程序執行緒。
執行緒的優先順序用數字來表示,範圍從1~10,主執行緒的預設優先順序為5

Thread.MIN_PRIORITY=1;Thread.MAX_PRIORITY=10;Thread.NORM_PRIORITY=5

當Java虛擬機器啟動時,通常會有一個非守護程式執行緒(通常呼叫某個指定類的名為 main的方法)
Java虛擬機器繼續執行執行緒直到發生以下任一情況:

  • 已呼叫類 Runtime的exit方法,並且安全管理器已允許執行退出操作。
  • 所有非守護程式執行緒的執行緒都已經死亡,要麼通過呼叫返回run方法,要麼丟擲一個超出run 方法傳播的異常。

問:執行緒與程序?:程序是CPU,記憶體等資源佔用的基本單位,執行緒是不能獨立佔有這些資源的;程序之間相互獨立,通訊比較困難,執行緒之間共享一塊記憶體區域,通訊方便

二.怎麼建立一個執行緒呢?

Thread中規定:有兩種方法可以建立新的執行執行緒。

  1. 宣告一個類是Thread類,該子類還應該覆蓋Thread類中的run方法,然後可以分配並啟動子類的示例。

    class MyThread extends Thread {

        @Override
        public void run() {
        //具體的方法
        System.out.println(Calendar.getInstance().getTime());//系統時間
        }
    }
    

然後建立一個執行緒並開始執行:

MyThread myThread=new MyThread();
myThread.start();
  1. 宣告一個實現 Runnable介面的類, 該類然後實現 run 方法, 然後可以分配類的例項,在建立 Thread時作為引數傳遞,然後啟動。
class MyThreard implements Runnable {
    public void run() {
        System.out.println(Calendar.getInstance().getTime());
    }
}

然後建立一個執行緒並開始執行:

MyThreard p = new MyThreard();
new Thread(p).start();

三.為什麼使用多執行緒?

多執行緒指的是在單個程式中可以同時執行多個不同的執行緒,執行不同的任務

  • 更高的執行效率,——並行;
  • 多執行緒是模組化的程式設計模型;
  • 與程序相比,執行緒的建立和切換開銷更小;
  • 通訊方便;
  • 能簡化程式的結構,便於理解和維護;更高的資源利用率。

注:多執行緒上下文切換的效能損耗:上下文切換(執行緒切換,程序切換,模式切換,地址空間切換)——中斷處理(硬體中斷,軟體中斷—執行緒被掛起);多工處理(每個程式都有相應的處理時間片);使用者態切換。

四.多執行緒的安全問題

簡單測試你的執行緒是否安全:如果你的程式碼在多執行緒下執行和在單執行緒下執行永遠都能獲得一樣的結果,那麼你的程式碼就是執行緒安全的。
如果不一致,那就可能是多執行緒的資源安全有問題,常見的情況如下:

1.臨界資源問題:多個執行緒同時訪問相同的資源並進行讀寫操作

解決思路:避免競態條件;多執行緒同步,必須獲得每一個執行緒物件的鎖(lock)

示例程式碼(一個執行緒進行加操作,一個執行緒進行減操作):

public class Stack {
    int idx=0;
    char[] data=new char[10];
    public void push(char c) {
        synchronized (this) {//在執行該程式碼段時必須取得物件鎖
            data[idx]=c; 
            idx++;     }
    }
    public synchronized char pop() {//在執行該方法時必須取得物件鎖
        idx--;
        return data[idx];
    }
}

同步實現的方法:(這裡上一張百度的圖,個人覺得總結的還是