多線程編程
在Android中系統(tǒng)要求網(wǎng)絡(luò)訪問必須在子線程中進(jìn)行庄呈,否則會拋出異常遇伞,避免主線程被耗時操作阻塞而產(chǎn)生ANR
線程基礎(chǔ)
進(jìn)程與線程
什么是進(jìn)程
進(jìn)程是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)块饺,是程序在一個數(shù)據(jù)集合上運(yùn)行的過程,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位昔案。
什么是線程
線程是操作系統(tǒng)調(diào)度的最小單元帝牡,也叫做輕量級進(jìn)程,在一個進(jìn)程中可以創(chuàng)建多個線程堕扶,這些線程都擁有各自的計數(shù)器碍脏、堆棧和局部變量等屬性,并且能夠訪問共享的內(nèi)存變量
線程的狀態(tài)
Java線程在運(yùn)行的生命周期中會有6種狀態(tài)
- New:新創(chuàng)建狀態(tài)稍算。還沒有調(diào)用start()方法
- Runnable:可運(yùn)行狀態(tài)典尾。一旦調(diào)用start方法,線程就處于Runnable狀態(tài)糊探,一個可運(yùn)行的線程可能正在運(yùn)行也可能沒有運(yùn)行钾埂。取決于操作系統(tǒng)給線程提供的運(yùn)行時間
- Blocked:阻塞狀態(tài),表示線程被鎖阻塞
- Waiting:等待狀態(tài)科平。表示線程暫時不活動
- Tiimed waiting:超時等待狀態(tài)
-
Terminated:終止?fàn)顟B(tài)褥紫。表示當(dāng)前線程已經(jīng)執(zhí)行完畢。
線程的狀態(tài)
線程狀態(tài)切換過程:
線程創(chuàng)建后瞪慧,調(diào)用Thread的start方法髓考,開始進(jìn)入運(yùn)行狀態(tài),當(dāng)線程執(zhí)行wait方法后弃酌,線程進(jìn)入等待狀態(tài)氨菇,進(jìn)入等待狀態(tài)的線程需要其他線程通知才能返回運(yùn)行狀態(tài)。超時等待相當(dāng)于在等待狀態(tài)加上了時間限制妓湘,如果超過時間限制查蓉,則線程返回運(yùn)行狀態(tài)。
創(chuàng)建線程
繼承Thread類榜贴,重寫run()方法
實現(xiàn)Runnable接口豌研,實現(xiàn)該接口的run()方法
實現(xiàn)Callable接口,重寫call()方法
Volatile
Volatile關(guān)鍵字為實例域的同步訪問提供了免鎖的機(jī)制。如果聲明一個域為volatile鹃共,那么編譯器和虛擬機(jī)就知道該域是可能被另一個線程并發(fā)更新的鬼佣。
Java內(nèi)存模型
Java中的堆內(nèi)存用來存儲對象實例,堆內(nèi)存是被所有線程共享的運(yùn)行時內(nèi)存區(qū)域及汉,因此堆內(nèi)存存在內(nèi)存可見性的問題沮趣。而局部變量、方法定義的參數(shù)則不會在線程之間共享坷随,不會存在內(nèi)存可見性問題房铭,也不受內(nèi)存模型的影響。
在Java中內(nèi)存模型定義了線程和主存之間的抽象關(guān)系:線程之間的共享變量存儲在主存中温眉,每個線程都有一個私有的本地內(nèi)存缸匪,本地內(nèi)存中存儲了該線程共享變量的副本。
線程A與B之間若要通信类溢,要經(jīng)歷以下幾個步驟:
- 線程A把線程A本地內(nèi)存中更新過的共享變量刷新到主內(nèi)存中去
- 線程B到主存中去讀取線程A之前已更新過的共享變量
Volatile關(guān)鍵字
當(dāng)一個共享變量被Volatile修飾之后凌蔬,就具備了兩個含義,
- 一個是線程修改了變量的值時闯冷,變量的新值對其他線程是立即可見的
- 禁止使用指令重排序砂心,指令重排序是指編譯器或運(yùn)行時環(huán)境為了優(yōu)化程序性能而采取的對指令進(jìn)行重新排序的一種手段
volatile保證了操作的可見性、有序性蛇耀,不保證原子性
線程池
線程池的種類
- FixedThreadPool
FixedThreadPool是可重用固定線程數(shù)的線程池 - CachedThreadPool
CachedThreadPool是一個根據(jù)需要創(chuàng)建線程的線程池 - SingleThreadExecutor
SingleThreadExecutor是使用單個工作線程的線程池
4.ScheduledThreadPool
ScheduledThreadPool是一個能實現(xiàn)定時和周期性任務(wù)的線程池