Android執行緒管理之Thread使用總結

總李寫程式碼發表於2016-06-21

前言

     最近在一直準備總結一下Android上的執行緒管理,今天先來總結一下Thread使用。

     執行緒管理相關文章地址:

實現Thread兩種方式

   1.)繼承Thread類
 /**
     * 繼承Thread方式
     */
    private class SyncThread extends Thread {

        SyncThread(String name) {
            super(name);
        }

        @Override
        public void run() {
           //執行耗時操作
        }
    }

 示例:

 SyncThread syncThread1 = new SyncThread("執行緒一");
 SyncThread syncThread2 = new SyncThread("執行緒二");
 SyncThread syncThread3 = new SyncThread("執行緒三");

 syncThread1.start();
 syncThread2.start();
 syncThread3.start();
 2.)實現Runnable介面
   /**
     * 實現Runnable方式
     */
    private class SyncRunnable implements Runnable {
        @Override
        public void run() {
            //執行耗時操作
        }
    }

示例:

SyncRunnable syncRunnable = new SyncRunnable();
Thread syncThread1 = new Thread(syncRunnable, "執行緒一");
Thread syncThread2 = new Thread(syncRunnable, "執行緒二");
Thread syncThread3 = new Thread(syncRunnable, "執行緒三");

syncThread1.start();
syncThread2.start();
syncThread3.start();

Thread主要函式

run()//包含執行緒執行時所執行的程式碼 

start()//用於啟動執行緒

sleep()/sleep(long millis)//執行緒休眠,交出CPU,讓CPU去執行其他的任務,然後執行緒進入阻塞狀態,sleep方法不會釋放鎖

yield()//使當前執行緒交出CPU,讓CPU去執行其他的任務,但不會是執行緒進入阻塞狀態,而是重置為就緒狀態,yield方法不會釋放鎖

join()/join(long millis)/join(long millis,int nanoseconds)//等待執行緒終止,直白的說 就是發起該子執行緒的執行緒 只有等待該子執行緒執行結束才能繼續往下執行

wait()//交出cpu,讓CPU去執行其他的任務,讓執行緒進入阻塞狀態,同時也會釋放鎖

interrupt()//中斷執行緒,自stop函式過時之後,我們通過interrupt方法和isInterrupted()方法來停止正在執行的執行緒,注意只能中斷已經處於阻塞的執行緒

getId()//獲取當前執行緒的ID

getName()/setName()//獲取和設定執行緒的名字

getPriority()/setPriority()//獲取和這是執行緒的優先順序 一般property用1-10的整數表示,預設優先順序是5,優先順序最高是10,優先順序高的執行緒被執行的機率高

setDaemon()/isDaemo()//設定和判斷是否是守護執行緒

currentThread()//靜態函式獲取當前執行緒

Thread執行緒主要狀態

(1) New  一旦被例項化之後就處於new狀態

(2) Runnable 呼叫了start函式之後就處於Runnable狀態

(3) Running 執行緒被cpu執行 呼叫run函式之後 就處於Running狀態

 (4)   Blocked 呼叫join()、sleep()、wait()使執行緒處於Blocked狀態

 (5)   Dead    執行緒的run()方法執行完畢或被中斷或被異常退出,執行緒將會到達Dead狀態

如何停止一個執行緒

通過上面的函式列表,我可以知道通過interrupt方法和isInterrupted()方法來停止正在執行的執行緒,首先必須先讓執行緒處於阻塞狀態

    /**
     * 銷燬執行緒方法
     */
    private void destroyThread() {
        try {
            if (null != thread && Thread.State.RUNNABLE == thread .getState()) {
                try {
                    Thread.sleep(500);
                    thread .interrupt();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            thread = null;
        }
    }

Thread執行緒同步問題

 執行緒的同步是為了防止多個執行緒訪問一個資料物件時,造成資料不一致的問題。

1.)舉例說明:比如多執行緒操作一個全域性變數
    private int count = 100;
    private boolean isRunning = false;
    private void test1() {
        isRunning=true;
        SyncThread syncThread1 = new SyncThread("執行緒一");
        SyncThread syncThread2 = new SyncThread("執行緒二");
        SyncThread syncThread3 = new SyncThread("執行緒三");

        syncThread1.start();
        syncThread2.start();
        syncThread3.start();

    }

    /**
     * 繼承Thread方式
     */
    private class SyncThread extends Thread {

        SyncThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            while (isRunning) {
                count();
            }
        }
    }

未加同步的count函式

    private void count() {
        if (count > 0) {
            Log.e(TAG, Thread.currentThread().getName() + "--->" + count--);
        } else {
            isRunning = false;
        }
    }

執行結果:仔細觀察會發現有資料錯亂的現象

新增同步的count函式

    private void count() {
        synchronized (this) {
            if (count > 0) {
                Log.e(TAG, Thread.currentThread().getName() + "--->" + count--);
            } else {
                isRunning = false;
            }
        }
    }

執行結果

 2.)執行緒同步的幾種方式

   同樣還是以上面的為例

  (1)同步函式

   private synchronized void count() {
        if (count > 0) {
            Log.e(TAG, Thread.currentThread().getName() + "--->" + count--);
        } else {
            isRunning = false;
        }
    }

(2)同步程式碼塊 

  private void count() {
        synchronized (this) {
            if (count > 0) {
                Log.e(TAG, Thread.currentThread().getName() + "--->" + count--);
            } else {
                isRunning = false;
            }
        }
    }

(3)使用特殊域變數(volatile)實現執行緒同步

 private volatile int count = 1000;

  a.volatile關鍵字為域變數的訪問提供了一種免鎖機制,
  b.使用volatile修飾域相當於告訴虛擬機器該域可能會被其他執行緒更新,
  c.因此每次使用該域就要重新計算,而不是使用暫存器中的值
  d.volatile不會提供任何原子操作,它也不能用來修飾final型別的變數

(4)使用重入鎖實現執行緒同步

  ReentrantLock() : 建立一個ReentrantLock例項 

  lock() : 獲得鎖 

  unlock() : 釋放鎖 
    private void count() {
        lock.lock();
        if (count > 0) {
            Log.e(TAG, Thread.currentThread().getName() + "--->" + count--);
        } else {
            isRunning = false;
        }
        lock.unlock();
    }

 

相關文章