Android線程

Android的應(yīng)用層都是Java寫的脚作,所以很多語法上的東西就是Java的,只不過某些類在原有基礎(chǔ)上進行了包裝,畢竟android跟java web兢孝,se之類的生產(chǎn)環(huán)境不一樣浇坐,而線程又是java中一塊很重要的知識睬捶,線程控制的好不好也關(guān)系到應(yīng)用性能提升大不大,畢竟不是Java出身近刘,所以簡單的說說java的線程

多線程

扯到線程擒贸,就不免會說道進程,簡答來數(shù)進程就是內(nèi)存中運行的應(yīng)用程序有獨立的內(nèi)存空間觉渴,而線程則是進程的組成介劫,線程即達成目標(biāo)的一個任務(wù)。
那么我們?yōu)槭裁词褂枚嗑€程呢案淋?如今cpu已經(jīng)進入4核座韵,八核時代,如何充分利用硬件資源去實現(xiàn)一個程序催生了多線程踢京。
舉個簡單的例子誉碴,運一批貨,在一個雙車道的道路上瓣距,如果按順序發(fā)車的話黔帕,貨物到達肯定要慢點,同時發(fā)貨的話蹈丸,理想情況時間就少了一半成黄。

Java的多線程
一般Java中實現(xiàn)多線程無非兩種方式:
  • 繼承Thread
class NewThread extends Thread {    
@Override    
public void run() {        
        super.run();    
        }
}
  • new Thread將任務(wù)放到Runnable里面
new Thread(new Runnable() {    
@Override    
public void run() {            
      }
}).start();

需要注意的是,調(diào)用start方法后逻杖,線程不是立即開啟奋岁,而是等待系統(tǒng)分配時間片(由于系統(tǒng)是隨機分配時間片,所以線程的調(diào)度存在不確定性)

線程狀態(tài)
線程狀態(tài).png
  • 新建狀態(tài)(New):**當(dāng)線程對象對創(chuàng)建后荸百,即進入了新建狀態(tài)闻伶,如:Thread t = new MyThread();
  • 就緒狀態(tài)(Runnable):**當(dāng)調(diào)用線程對象的start()方法(t.start();),線程即進入就緒狀態(tài)管搪。處于就緒狀態(tài)的線程虾攻,只是說明此線程已經(jīng)做好了準(zhǔn)備铡买,隨時等待CPU調(diào)度執(zhí)行,并不是說執(zhí)行了t.start()此線程立即就會執(zhí)行霎箍;
  • 運行狀態(tài)(Running):**當(dāng)CPU開始調(diào)度處于就緒狀態(tài)的線程時奇钞,此時線程才得以真正執(zhí)行,即進入到運行狀態(tài)漂坏。注:就 緒狀態(tài)是進入到運行狀態(tài)的唯一入口景埃,也就是說,線程要想進入運行狀態(tài)執(zhí)行顶别,首先必須處于就緒狀態(tài)中谷徙;
  • 阻塞狀態(tài)(Blocked):處于運行狀態(tài)中的線程由于某種原因,暫時放棄對CPU的使用權(quán)驯绎,停止執(zhí)行完慧,此時進入阻塞狀態(tài),直到其進入到就緒狀態(tài)剩失,才 有機會再次被CPU調(diào)用以進入到運行狀態(tài)屈尼。根據(jù)阻塞產(chǎn)生的原因不同,阻塞狀態(tài)又可以分為三種:
    1.等待阻塞:運行狀態(tài)中的線程執(zhí)行wait()方法拴孤,使本線程進入到等待阻塞狀態(tài)脾歧;
    2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態(tài)演熟;
    3.其他阻塞 -- 通過調(diào)用線程的sleep()或join()或發(fā)出了I/O請求時鞭执,線程會進入到阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時芒粹、join()等待線程終止或者超時兄纺、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)化漆。
  • 死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法囤热,該線程結(jié)束生命周期。
線程優(yōu)先級

Java的線程是具有優(yōu)先級的获三,可以通過setPriority()設(shè)置線程的優(yōu)先級,控制線程的重要性(擁有較大機會獲取系統(tǒng)調(diào)度)锨苏,Thread有3個控制線程優(yōu)先級的常量

  • static int MAX_PRIORITY ----10
  • static int MIN_PRIORITY-----1
  • static int NORM_PRIORITY---5
常見線程常用函數(shù)

1.sleep(long mills):讓當(dāng)前線程休眠指定的毫秒數(shù)
2.join():讓主線程等待調(diào)用該函數(shù)的線程結(jié)束再執(zhí)行(所在線程等待調(diào)用該方法的線程變量所在的線程執(zhí)行完畢)
應(yīng)用情形:當(dāng)主線程需要實時使用子線程的處理結(jié)果疙教,有點像阻塞式的編程
3.yield():暫停當(dāng)前線程,讓出時間片
實質(zhì)是將該線程調(diào)回到runnable狀態(tài)重新等待調(diào)度伞租,高優(yōu)先級線程會被先調(diào)用贞谓,同等級無法保證讓出時間片(進入了統(tǒng)一等待隊列,系統(tǒng)還是會選中當(dāng)前線程)
4.setPriority(int priority):上面有說過
5.interrupt():野蠻方式中斷線程葵诈,可能會導(dǎo)致資源無法釋放
6.wait():等待擁有同樣資源鎖的線程的執(zhí)行裸弦,線程同步的一個方法祟同,主要關(guān)系到對資源鎖定問題,后面討論
7.notify():喚醒擁有同樣資源鎖的線程


備注:sleep()與wait()區(qū)別:sleep的同時不釋放同步鎖理疙,也就是說sleep的同時擁有同樣資源鎖的線程不會拿到時間片,而wait()的時候是釋放同步鎖晕城,讓其他擁有同等資源鎖的線程獲得時間片(必須放在synchronized塊內(nèi))


線程同步問題

這個應(yīng)該是線程里面最重要,也是最難的部分了窖贤,主要由于系統(tǒng)調(diào)度的不確定性引起砖顷,一般不做線程同步的話,出現(xiàn)了某些問題赃梧,調(diào)試都很難調(diào)試出來
數(shù)據(jù)的同步在數(shù)據(jù)庫里面非常常見滤蝠,設(shè)想線程A,B同時對一個變量進行++操作

int res = 0;
class A extends Thread {    
@Override   
 public void run() {       
super.run();       
 res=res+1;       
System.out.print("A:res" + res);    
}}
class B extends Thread {   
 @Override    
public void run() {        
super.run();       
 res=res+1;        
System.out.print("B:res" + res);    }}```
上述代碼會有兩種不同的輸出
A:1
B:2
或者
B:1
A:2
這可能跟我預(yù)想的結(jié)果就不一樣了,因此我們需要對資源進行同步
######synshronized關(guān)鍵字
這是用來加同步鎖的關(guān)鍵字授嘀,他有兩種作用域
1. 對象:某個對象內(nèi)synchronized methodA(){}物咳,可以鎖住這個對象的該方法(若該對象擁有多個synchronized方法,加鎖后其它synchronized方法也無法調(diào)用)蹄皱,但不影響不同對象
2. 類:synchronized static methodA(){},對所有對象起效
除了方法前可以加synchronized览闰,某個區(qū)塊也可以加,他們的實質(zhì)都是鎖對象

```synchronized methodA(){} //鎖對象 
synchronized static methodA(){} //鎖類```
等同于 
```methodA(){synchronized(obj){} } //鎖對象 
methodA(){
synchronized(obj.class){}}```
synchronized搭配wait(),notify()方法使用,wait()調(diào)用后夯接,不執(zhí)行wait()后面的代碼焕济,notify()后繼續(xù)執(zhí)行上次wait()后的代碼

######lock同步鎖
方便的解決同步問題的另一方案

class X {
// 顯示定義Lock同步鎖對象,此對象與共享資源具有一對一關(guān)系
private final Lock lock = new ReentrantLock();
public void m(){
// 加鎖 lock.lock();
//... 需要進行線程安全同步的代碼
// 釋放Lock鎖
lock.unlock(); } }


可以參考下Condition實現(xiàn)

######線程數(shù)據(jù)傳遞

由于線程的不確定性盔几,所以線程間的通信晴弃,也不像普通的同步模式下的通信
1. 構(gòu)造方法傳遞數(shù)據(jù) 由于構(gòu)造方法是線程一開始就傳入所以不存在同步問題,可通過重載構(gòu)造方法傳入?yún)?shù)
2. 通過公開方法賦值逊拍,類的屬性器賦值或者讀取
前兩個都建立在宿主線程與被調(diào)線程的通信上鞠,下面就是線程與線程之間(并無直接關(guān)聯(lián))
3. 通過同步控制,訪問共有對象(synchronized芯丧,wait芍阎,notify等)
4. 管道流(這個不是很了解,望高手指教)
---
接下來就談?wù)凴unnable缨恒,Callable<V>,Future谴咸。
由于Runnable里面的run函數(shù)返回為void,因此我們無法觀察任務(wù)的狀態(tài)骗露,Callable<V>正好解決了這個問題

public interface Callable<V> {
/**

  • Computes a result, or throws an exception if unable to do so.
  • @return computed result
  • @throws Exception if unable to compute a result
    */
    V call() throw Exception;
    }```
    Future又是什么東西呢,
public interface Future<V> {  
boolean cancel(boolean mayInterruptIfRunning);   
boolean isCancelled();   
boolean isDone();
V get() throws InterruptedException,ExecutionException;   
V get(long timeout, TimeUnit unit)        
throws InterruptedException, ExecutionException, TimeoutException;
}```
* cancel取消任務(wù)
* isCancelled 返回任務(wù)是否被取消
* get 獲取任務(wù)這行結(jié)果岭佳,阻塞方法,等到任務(wù)正常完成才會返回值
* get(long萧锉,TimeUnit)在規(guī)定時間內(nèi)無返回結(jié)果就返回null

所以Future只是個接口因此我們只能使用它的實現(xiàn)

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}```
FutrueTask實現(xiàn)了RunnableFuture<v>,RunnableFuture<v>又繼承自Runnable珊随,F(xiàn)uture<v>,Callable<v>經(jīng)常搭配ExcutorService一起使用

public FutureTask(Callable<V> callable) {}
public FutureTask(Runnable runnable, V result) {}```
FutureTask提供了兩個構(gòu)造函數(shù),實質(zhì)都是實現(xiàn)Runnable與Future<v>接口,[FutureTask,Callable<V>使用](http://www.cnblogs.com/dolphin0520/p/3949310.html)

----
寫作思路大抵發(fā)散性的 有相關(guān)的就查閱下叶洞,篇幅比較長鲫凶,若有錯誤請大家指正,下次接著寫線程池
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末衩辟,一起剝皮案震驚了整個濱河市螟炫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惭婿,老刑警劉巖不恭,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異财饥,居然都是意外死亡换吧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門钥星,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沾瓦,“玉大人,你說我怎么就攤上這事谦炒」彷海” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵宁改,是天一觀的道長缕探。 經(jīng)常有香客問我,道長还蹲,這世上最難降的妖魔是什么爹耗? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮谜喊,結(jié)果婚禮上潭兽,老公的妹妹穿的比我還像新娘。我一直安慰自己斗遏,他們只是感情好山卦,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诵次,像睡著了一般账蓉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逾一,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天剔猿,我揣著相機與錄音,去河邊找鬼嬉荆。 笑死,一個胖子當(dāng)著我的面吹牛酷含,可吹牛的內(nèi)容都是我干的鄙早。 我是一名探鬼主播汪茧,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼限番!你這毒婦竟也來了舱污?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤弥虐,失蹤者是張志新(化名)和其女友劉穎扩灯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霜瘪,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡珠插,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颖对。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捻撑。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖缤底,靈堂內(nèi)的尸體忽然破棺而出顾患,到底是詐尸還是另有隱情,我是刑警寧澤个唧,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布江解,位于F島的核電站,受9級特大地震影響徙歼,放射性物質(zhì)發(fā)生泄漏犁河。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一鲁沥、第九天 我趴在偏房一處隱蔽的房頂上張望呼股。 院中可真熱鬧,春花似錦画恰、人聲如沸彭谁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缠局。三九已至,卻和暖如春考润,著一層夾襖步出監(jiān)牢的瞬間狭园,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工糊治, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唱矛,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像绎谦,于是被迫代替她去往敵國和親管闷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容