Android線程管理之Thread使用總結


前言

     最近在一直准備總結一下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();
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM