前言html
最近在一直準備總結一下Android上的線程管理,今天先來總結一下Thread使用。java
線程管理相關文章地址:多線程
/** * 繼承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();
/** * 實現Runnable方式 */ private class SyncRunnable implements Runnable { @Override public void run() { //執行耗時操做 } }
示例:ide
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();
run()//包含線程運行時所執行的代碼 函數
start()//用於啓動線程this
sleep()/sleep(long millis)//線程休眠,交出CPU,讓CPU去執行其餘的任務,而後線程進入阻塞狀態,sleep方法不會釋放鎖spa
yield()//使當前線程交出CPU,讓CPU去執行其餘的任務,但不會是線程進入阻塞狀態,而是重置爲就緒狀態,yield方法不會釋放鎖線程
join()/join(long millis)/join(long millis,int nanoseconds)//等待線程終止,直白的說 就是發起該子線程的線程 只有等待該子線程運行結束才能繼續往下運行
code
wait()//交出cpu,讓CPU去執行其餘的任務,讓線程進入阻塞狀態,同時也會釋放鎖
interrupt()//中斷線程,自stop函數過期以後,咱們經過interrupt方法和isInterrupted()方法來中止正在運行的線程,注意只能中斷已經處於阻塞的線程
getId()//獲取當前線程的ID
getName()/setName()//獲取和設置線程的名字
getPriority()/setPriority()//獲取和這是線程的優先級 通常property用1-10的整數表示,默認優先級是5,優先級最高是10,優先級高的線程被執行的機率高
setDaemon()/isDaemo()//設置和判斷是不是守護線程
currentThread()//靜態函數獲取當前線程
(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; } }
線程的同步是爲了防止多個線程訪問一個數據對象時,形成數據不一致的問題。
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; } } }
執行結果
一樣仍是以上面的爲例
(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() : 得到鎖
private void count() { lock.lock(); if (count > 0) { Log.e(TAG, Thread.currentThread().getName() + "--->" + count--); } else { isRunning = false; } lock.unlock(); }