多線程的總結

1.談談你對線程和進程的理解?
(1)進程是正在執行的程序
(2)線程進程中用於控制程序執行的控制單元(執行路徑)
(3)進程中至少有一個線程,對於JVM,啓動時至少有兩個線程:JVM的主線程和JVM的垃圾回收線程
2.多線程(多線程並行和併發的區別)
(1)並行就是兩個任務同時運行,就是甲任務進行的同時,乙任務也在進行。(需要多核CPU)
(2)併發是指兩個任務都請求運行,而處理器只能按受一個任務,就把這兩個任務安排輪流進行,由於時間間隔較短,使人感覺兩個任務都在運行。
(3)比如我跟兩個網友聊天,左手操作一個電腦跟甲聊,同時右手用另一臺電腦跟乙聊天,這就叫並行。
(4)如果用一臺電腦我先給甲發個消息,然後立刻再給乙發消息,然後再跟甲聊,再跟乙聊。這就叫併發。
3.多線程(兩種方式的區別以及兩種實現方式的過程)(掌握)
(1)查看源碼的區別:
* a.繼承Thread : 由於子類重寫了Thread類的run(), 當調用start()時, 直接找子類的run()方法
* b.實現Runnable : 構造函數中傳入了Runnable的引用, 成員變量記住了它, start()調用run()方法時內部判斷成員變量Runnable的引用是否爲空,
不爲空編譯時看的是Runnable的run(),運行時執行的是子類的run()方法

(2)繼承Thread
    * 好處是:可以直接使用Thread類中的方法,代碼簡單
    * 弊端是:如果已經有了父類,就不能用這種方法
(3)實現Runnable接口
    * 好處是:即使自己定義的線程類有了父類也沒關係,因爲有了父類也可以實現接口,而且接口是可以多實現的
    * 弊端是:不能直接使用Thread中的方法需要先獲取到線程對象後,才能得到Thread的方法,代碼複雜
  • ①通過繼承Thread類,並改寫run()方法實現一個線程
  • ②創建一個Runnable對象
  • ③通過Handler啓動線程

啓動方式一

public class MyThread extends Thread{
    //繼承Thread類,改寫run 方法
    private final static String TAG = "MyThread"
    public void run(){
        for(int i=0,i<100;i++){
            Log.e(TAG,Thread.currentTHread().getName + "i = " + i);
        }
    }
}

**啓動**
new MyThread().start();


啓動方式二


public void MyRunnable implements Runnable{
    private final static String TAG = "MyThread";
    @Override
    public void run(){
            for(int i =0,i<100,i++){
                    Log.e(TAG,Thread.currentThread().getName() + "i = " + i);
        }
    }
}


**啓動:**
new Thread(new MyThread()).start();
**啓動:**

 btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                           ...
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });

啓動方式三
通過Handler 啓動線程

public void MyActivity extends Activity{
    private final static String TAG = "MyActivity";
    private int count = 0;
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable(){
                public void run(){
                        Log.e(TAG,Thread.currentThread().getName() + "count=" + count);
                        count++;
                        setTitle(""+count);
                        //間隔時間 每6秒執行一次
                        handler.postDelayed(handler,6000);
        }
    }
}

@Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        // 通過Handler啓動線程  
        mHandler.post(mRunnable);  //發送消息,啓動線程運行
    }  

      @Override      
         protected void onDestroy() {       
             //將線程銷燬掉       
             mHandler.removeCallbacks(mRunnable);       
             super.onDestroy();       
         }       

} 

4.sleep和wait的區別?
(1)sleep是讓線程休眠,必須給定休眠的時間,時間到了後自動醒來,不需要喚醒,休眠時不放棄cpu的執行權
(2)wait是讓線程等待,可以給時間,也可以不等時間,但是必須要喚醒才能醒來(使用notify或者notifyAll),等待時放棄cpu的執行權
(3)sleep方法是Thread類中定義的方法,wait是Object中定義的方法
(4)wait用在同步代碼塊或者同步方法中,sleep可以在任何地方使用
(5)sleep必須捕獲異常,wait不用捕獲異常

5.休眠線程、守護線程、加入線程、禮讓線程
(1)休眠線程:控制當前線程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000納秒 1000000000
(2)守護線程:設置一個線程爲守護線程, 該線程不會單獨執行, 當其他非守護線程都執行結束後, 自動退出
(3)加入線程:當前線程暫停, 等待指定的線程執行結束後, 當前線程再繼續
(4)禮讓線程:yield讓出cpu

6.同步代碼塊,同步方法,靜態同步方法的區別?以及什麼時候使用同步?
* 當多線程併發, 有多段代碼同時執行時, 我們希望某一段代碼執行的過程中CPU不要切換到其他線程工作. 這時就需要同步.
* 如果兩段代碼是同步的, 那麼同一時間只能執行一段, 在一段代碼沒執行結束之前, 不會執行另外一段代碼.
(1).多線程操作共享數據
(2).有多條語句在操作共享數據
(3).要使用同一個鎖
(4)同步代碼塊可以使用任意對象作爲鎖對象,同步方法的鎖爲this,靜態同步方法的鎖爲所在類的字節碼對象
7.什麼是死鎖?舉例說明?
解釋:兩個線程,各自拿着自己的鎖,而又想獲取對方的鎖,而雙方誰都不讓,就會出現死鎖
多線程同步的時候, 如果同步代碼嵌套, 使用相同鎖, 就有可能出現死鎖
舉例:
(1)兩個人上廁所,而廁所有兩把鎖
(2)還有上課講的兩根筷子的故事

8.設計模式?
(1)包裝設計模式(*)
(2)模板設計模式(*)
(3)工廠設計模式(*)
(4)單例設計模式(*)
/*
* 餓漢式和懶漢式的區別
* 1,餓漢式是空間換時間,懶漢式是時間換空間
* 2,在多線程訪問時,餓漢式不會創建多個對象,而懶漢式有可能會創建多個對象
*/
(5)動態代理設計模式(*)
(6)適配器設計模式
9.說一下你所學過的線程安全的類?
(1)看源碼:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)
(2)Vector是線程安全的,ArrayList是線程不安全的
(3)StringBuffer是線程安全的,StringBuilder是線程不安全的
(4)Hashtable是線程安全的,HashMap是線程不安全的
10.說一下你對線程間的通信的理解?
(1)什麼時候需要通信
* 多個線程併發執行時, 在默認情況下CPU是隨機切換線程的
* 如果我們希望他們有規律的執行, 就可以使用通信, 例如每個線程執行一次打印
(2)怎麼通信
* 如果希望線程等待, 就調用wait()
* 如果希望喚醒等待的線程, 就調用notify();
* 這兩個方法必須在同步代碼中執行, 並且使用同步鎖對象來調用

(3)多個線程通信的問題
    * notify()方法是隨機喚醒一個線程
    * notifyAll()方法是喚醒所有線程
    * JDK5之前無法喚醒指定的一個線程
    * 如果多個線程之間通信, 需要使用notifyAll()通知所有線程, 用while來反覆判斷條件

11.Runtime類,Timer類,互斥鎖(*******ReentrantLock)?
12.線程組的概念?線程池的概念?
13.線程的5種狀態?(必須掌握,詳細的請參考圖片)
(1)新建
(2)就緒
(3)運行
(4)阻塞
(5)死亡
14.線程實現的三種方式?

(1)繼承Thread類,重寫run函數
創建:
class xx extends Thread{
public void run(){
Thread.sleep(1000) //線程休眠1000毫秒,sleep使線程進入Block狀態,並釋放資源
}}
開啓線程:
對象.start() //啓動線程,run函數運行

(2)實現Runnable接口,重寫run函數
開啓線程:
Thread t = new Thread(對象) //創建線程對象
t.start()

(3)實現Callable接口,重寫call函數
Callable是類似於Runnable的接口,實現Callable接口的類和實現Runnable的類都是可被其它線程執行的任務。
Callable和Runnable有幾點不同:
①Callable規定的方法是call(),而Runnable規定的方法是run().
②Callable的任務執行後可返回值,而Runnable的任務是不能返回值的
③call()方法可拋出異常,而run()方法是不能拋出異常的。
④運行Callable任務可拿到一個Future對象,Future表示異步計算的結果。它提供了檢查計算是否完成的方法,以等
待計算的完成,並檢索計算的結果.通過Future對象可瞭解任務執行情況,可取消任務的執行,還可獲取任務執行的結果

發佈了39 篇原創文章 · 獲贊 42 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章