2022-10-25|閱讀時間 ‧ 約 8 分鐘

Android 進程與線程整理

    概要

    1. 在一個Android程序開始時,只會啟動一個Process(進程),關於此程序中的Activity與Service都會跑在這個Process之內。
    2. 而一個Process之中也會有很多個Thread,當一個Process被創造時,也會同時創造出一個Thread(Main Thread),所有的任務也都在一個Thread中進行,而主線程則負責UI介面的顯示和交互。
    3. 比較耗時的任務就需要交給子線程去做,避免主線程阻塞而導致ANR(Application not response)的情況。
    4. 實現多線程的方式分別有Thread, Runnable, Handler, AsyncTask, HandlerThread, IntentService的方式
    5. 可以想像進程跟線程為桌子跟人的狀況:

    一進程一線程:一個人在一張桌子上吃飯

    一進程多線程:多個人在一張桌子上吃飯

    多進程一線程:每個人在自己的桌子上吃飯

    進程

    進程的狀態變化:

    線程

    CPU調度與分派的最基本單位,比進程更小。

    使用的函數:

    run(): 線程運行時會執行的區塊

    start(): 啟動線程

    sleep()/sleep(long millis): 將線程進入睡眠,不會釋放lock

    yield(): 讓線程釋出CPU。

    wait(): 進入阻塞狀態,釋放lock。

    interrupt(): 中斷線程,僅限於阻塞狀態的線程。

    get/setName(): 設置線程的name。

    get/setPriority(): 設置線程的優先順序。

    setDaemon/isDaemo(): 設置是否為守護線程。

    currentThread(): 獲取當前線程。

    線程的狀態:

    新建 -> 就緒 -> 運行 -> 阻塞 -> 死亡

    程式法宣告的幾種方式:

    //1
    public class MyThread extends Thread{

    @Override
    public void run() {
    super.run();
    // do something
    }
    }
    public void goThread() {
        new MyThread().start();
    }
    //2.1 實現Runnable的方式
    public class MyRunnable implements Runnable{

    @Override
    public void run() {
    // do something
    }
    }
    new Thread(new MyRunnable()).start();

    //2.2 另一種啟動方式
    new Thread(new Runnable() {
    @Override
    public void run() {

    }
    }).start();
    //4 Handler啟動線程的方式
    private int count = 0;
    private Handler mHandler = new Handler();

    private Runnable runnable = new Runnable() {
    @Override
    public void run() {
    Log.i("download",Thread.currentThread().getName()+":"+count);
    count ++;
    mHandler.postDelayed(runnable,1000); // 执行后延迟1000毫秒再次执行,count已++
    }
    };

    進程與線程的比較

    多線程的幾種方法

    1. 繼承Thread
    2. 實現Runnable
    3. Handler
    4. AsyncTask
    5. HandlerThread

    HandlerThread

    一般我們在進行Handler時,預設是在Main Thread,如果要多開Thread來用Handler,則必須自行控制Looper,因此Android 開發了HandlerThread來整合這些狀況。

    通過繼承Threa類與封裝Handler類以達到兩者的效果。

    HandlerThread是能夠確保是循序且執行緒安全的,同時做到Thread與Handler的功能。

    程式碼:

    private void initHandleMessage() {
    //1. 創建HandlerThread實例對象
    //2. 啟動線程
    //3. 創建工作線程Handler以及override handleMessage()
    //4. 使用Message發送消息
    //5. 結束線程,停止消息循環
    private Handler mHandler = null;
        HandlerThread handlerThread = new  HandlerThread("newThread");   
    handlerThread.start();
    this.mHandler = new Handler(handlerThread.getLooper()) {//括號內放的是存取哪個線程looper(Looper.getMainLooper())
    @Override
    public void handleMessage(Message msg) {
    switch (msg.what) {
    case 1:
    ...
            }
        Message msg = Message.obtain();
    msg.what = 2;
    msg.obj = "B";
    Handler handler = this.mHandler;
    handler.sendMessage(Message.obtain(handler, what: 1));
        mHandlerThread.quit();

    線程安全的幾種方式

    線程安全關乎於幾種特性:

    1. 在進行相關操作時,不會中途被其他線程干擾。
    2. 若一個線程修改了其中的變數,其他線程能夠立刻知道。
    3. 線程有保證他的順序。

    synchronized

    當在程式碼加入synchronized之後,其他線程必須等待先使用的線程調用完才能調用。目的是保證線程安全,並解決多線程中的並發同步問題。

    程式碼:

    public void method() {

    synchronized(this) {

    ….

    }

    或是

    public void f1() {

    synchronized(lock) { //鎖必須是公共變量才行

    }

    參考資料:

    分享至
    成為作者繼續創作的動力吧!
    © 2024 vocus All rights reserved.