前言:這里講的線程都不采用線程池,繼承Thread類和實(shí)現(xiàn)Runnable以及Callable都通過Thread來創(chuàng)建并啟動(dòng)劲妙,即這里的線程控制都是指Thread的方法
線程控制(即Thread類)主要有5個(gè)方法
- join線程:join()
- 后臺(tái)線程:setDaemon()
- 線程睡眠:sleep()
- 線程讓步:yield()
- 改變線程優(yōu)先級(jí):setPriority()
一. join線程
join線程指:讓一個(gè)線程等待另一個(gè)線程完成敬飒。
1. join():等待線程執(zhí)行完成
當(dāng)在A線程中調(diào)用B線程的join()方法時(shí)达舒,調(diào)用線程(A線程)將被阻塞浪箭,直到B線程執(zhí)行完為止矗积。
2. join(long millis):等待被join的線程最長(zhǎng)時(shí)間為millis毫秒
在A線程里調(diào)用B線程的join(long millis)方法,A將被阻塞悬钳,阻塞時(shí)間不超過millis盐捷。假如B線程需要10*1000毫秒才執(zhí)行完畢,而millis為5000默勾,那么B執(zhí)行5秒后碉渡,A和B都回到就緒狀態(tài)
3. join(long millis,int nanos): 等待被join的線程最長(zhǎng)時(shí)間為millis毫秒+nanos毫微秒
該方法忽略不用
public class JoinCallable implements Callable {
private int i=0;
@Override
public Object call() throws Exception {
for (;i<5;i++){
Log.d("MainActivity",Thread.currentThread().getName()+" i:"+i);
Thread.sleep(100);
}
return null;
}
}
//使用
private void joinCallable() {
try {
for (int i=0;i<6;i++){
Log.d("MainActivity",Thread.currentThread().getName()+":"+i);
if (i==3){
Callable joinCallable = new JoinCallable();
FutureTask task = new FutureTask(joinCallable);
Thread thread = new Thread(task, "join線程");
thread.start();
thread.join();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//運(yùn)行打印日志
2020-05-04 22:49:24.264 31878-31878/priv.hsj.thread D/MainActivity: main:0
2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:1
2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:2
2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:3
2020-05-04 22:49:24.267 31878-31914/priv.hsj.thread D/MainActivity: join線程 i:0
2020-05-04 22:49:24.368 31878-31914/priv.hsj.thread D/MainActivity: join線程 i:1
2020-05-04 22:49:24.469 31878-31914/priv.hsj.thread D/MainActivity: join線程 i:2
2020-05-04 22:49:24.569 31878-31914/priv.hsj.thread D/MainActivity: join線程 i:3
2020-05-04 22:49:24.671 31878-31914/priv.hsj.thread D/MainActivity: join線程 i:4
2020-05-04 22:49:24.777 31878-31878/priv.hsj.thread D/MainActivity: main:4
2020-05-04 22:49:24.777 31878-31878/priv.hsj.thread D/MainActivity: main:5
注意:join方法必須要在start方法后調(diào)用才有效
二. 后臺(tái)線程
后臺(tái)線程是在后臺(tái)運(yùn)行的,為其他的線程提供服務(wù)母剥,他也叫”守護(hù)線程“和”精靈線程???♀?“滞诺。
JVM的垃圾回收線程就是典型的后臺(tái)線程。
如果所有的前臺(tái)線程都死亡环疼,后臺(tái)線程就會(huì)自動(dòng)死亡习霹。
Thread類還提供了isDaemon()方法,用于判斷指定線程是否為后臺(tái)線程炫隶。
注意:setDaemon(true)必須必須要在start()方法前調(diào)用淋叶,否則會(huì)IllegalThreadStateException異常。
三. 線程睡眠
線程睡眠是讓當(dāng)前正在執(zhí)行的線程暫停一段時(shí)間伪阶,即阻塞一段時(shí)間
- sleep(long millis):讓當(dāng)前正在執(zhí)行的線程暫停millis毫秒煞檩,并進(jìn)入阻塞狀態(tài)
- sleep(long millis,int nanos):讓當(dāng)前正在執(zhí)行的線程暫停millis毫秒加nanos毫微秒。該方法忽略不用栅贴。
當(dāng)前線程調(diào)用sleep()方法進(jìn)入阻塞狀態(tài)后斟湃,在其睡眠時(shí)間段內(nèi),該線程不會(huì)獲得執(zhí)行的機(jī)會(huì)檐薯,即使系統(tǒng)中沒有其他可執(zhí)行的線程凝赛,處于sleep()中的線程也不會(huì)執(zhí)行。
sleep()時(shí)間過完后,由阻塞狀態(tài)轉(zhuǎn)為就緒狀態(tài)
四. 線程讓步
線程讓步是將線程轉(zhuǎn)入就緒狀態(tài)
當(dāng)前線程調(diào)用yield()方法進(jìn)入就緒狀態(tài)哄酝,線程調(diào)度器重新調(diào)度
線程調(diào)用yield()方法后將執(zhí)行機(jī)會(huì)讓給優(yōu)先級(jí)相同友存,或優(yōu)先級(jí)更高的線程
sleep()與yield方法區(qū)別
- sleep()是將線程轉(zhuǎn)入阻塞狀態(tài)。yield()是將該線程轉(zhuǎn)入就緒狀態(tài)
- sleep()期間陶衅,會(huì)給其他線程執(zhí)行機(jī)會(huì)屡立,其他所有線程機(jī)會(huì)平等,與優(yōu)先級(jí)無關(guān)搀军。yield()只會(huì)給優(yōu)先級(jí)相同或優(yōu)先級(jí)更高的線程執(zhí)行機(jī)會(huì)膨俐,即有可能某個(gè)線程調(diào)用yield()方法暫停之后,會(huì)立即再次獲得CPU
- sleep()方法聲明拋出異常罩句,而yield()沒有聲明拋出異常焚刺。
- sleep()比yield()有更好的可移植性,并發(fā)線程一般不會(huì)使用yield()
五. 改變線程優(yōu)先級(jí)
每個(gè)線程執(zhí)行時(shí)都具有一定的優(yōu)先級(jí)门烂,優(yōu)先級(jí)高的線程獲得較多的執(zhí)行機(jī)會(huì)乳愉,優(yōu)先級(jí)低的獲得較少的執(zhí)行機(jī)會(huì)。
每個(gè)線程默認(rèn)的優(yōu)先級(jí)都與創(chuàng)建它的父線程的優(yōu)先級(jí)相同屯远。
setPriority(int newPriority)方法參數(shù)取值范圍為1~10蔓姚,默認(rèn)為5,Thread類給了三個(gè)靜態(tài)常量
- MAX_PRIORITY:值為10
- MIN_PRIORITY:值為1
- NORM_PRIORITY:值為5
在開發(fā)中慨丐,盡量避免使用具體數(shù)字坡脐,應(yīng)使用三個(gè)靜態(tài)常量,這樣更具有移植性房揭。
上一篇:Android多線程(二)——線程的生命周期:http://www.reibang.com/p/0b9468cda0c7