線程的狀態(tài)
- NEW
- RUNNABLE
- BLOCKED:線程阻塞于鎖
- WAITING:等待狀態(tài),當(dāng)前線程需要等待其他線程通知或者中斷才能被喚醒。
- TIME_WAITING:超時(shí)等待,與waiting狀態(tài)不同的是,它可以在指定的時(shí)間到達(dá)時(shí)返回到運(yùn)行狀態(tài),不一定需要?jiǎng)e的線程的喚醒。
- TERMINATED
線程狀態(tài)變遷
- 從RUNNABLE變?yōu)閃AITING狀態(tài)可能的情況
object.wait();//等待object.notify()或者object.notifyAll();
threadA.join();//等待線程threadA執(zhí)行完畢
LockSupport.park();//important,等待相應(yīng)的uppark調(diào)用。
- 從RUNNABLE到TIME_WAITING類似于上,只是加上了超時(shí)返回。
Thread.sleep(long);
object.wait(long);
threadA.join(long);
LockSupport.park(long);
- 從RUNNABLE到阻塞狀態(tài)
等待進(jìn)入synchronized方法和synchronized代碼塊。注意:阻塞在concurrent包中的Lock接口的線程是等待狀態(tài)(因?yàn)榈讓邮褂玫腖ockSupport類中的方法)
線程的創(chuàng)建與銷毀
線程的創(chuàng)建
新建一個(gè)線程對象時(shí):init方法會(huì)從其父線程(當(dāng)前線程)繼承一些信息,比較重要的有(contextClassLoader,daemon,priority,可繼承的ThreadLocal)
線程的啟動(dòng)
thread.start();
中斷
中斷就相當(dāng)與線程與線程之間發(fā)消息一樣,假如threadA中調(diào)用threadB.interrupt(), 那么threadB就會(huì)收到這個(gè)中斷消息并做出響應(yīng)(比如,threadB正在sleep,那么sleep會(huì)馬上結(jié)束并拋出InterruptedException)
對thread.isInterrupted()和Thread.interrupted(檢查當(dāng)前線程中斷表示位)的返回值取決與線程是否還有未被處理的中斷消息。對于上面的例子來說,thread.isInterrupted()返回false,因?yàn)橹袛嘞⒁呀?jīng)被消耗了(返回InterruptedException)
安全的終止線程demo
通過這個(gè)Runner生成的線程對象可以通過中斷關(guān)閉,或者cancel()調(diào)用關(guān)閉
private static class Runner implements Runnable{
private volatile boolean on = true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()){
//do
}
}
public void cancel() {
on = false;
}
}
線程間通信
volatile和synchronized關(guān)鍵字的內(nèi)存語義
等待通知機(jī)制
這里主要涉及Object類的幾個(gè)方法
wait();
wait(long);//超時(shí)等待
notify();
notifyAll();
這里以一段生產(chǎn)者消費(fèi)者代碼,這樣寫有點(diǎn)冗余。
private class Container{
private int maxCap;
private int curCap;
private int toPut;
private int toGet;
private int[] data;
Container(int cap){
this.maxCap = cap;
data = new int[cap];
curCap = toGet = toPut = 0;
}
public int get(){
synchronized (this){
while (curCap <= 0)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
int tmp = data[toGet];
curCap--;
toGet = toGet + 1 < maxCap ? toGet + 1: 0;
this.notifyAll();//this can notify the consumer thread also.
return tmp;
}
}
public void put(int i){
synchronized (this){
while (curCap == maxCap){
try{
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data[toPut] = i;
curCap ++;
toPut = toPut + 1 < maxCap ? toPut + 1 : 0;
this.notifyAll();
}
}
}
Thread.join()
如在threadA中調(diào)用threadB.join()那么就會(huì)等threadB返回之后才執(zhí)行A線程中threadB.join()之后的內(nèi)容。
這里其實(shí)是相當(dāng)于 threadB.wait(); 然后線程銷毀時(shí)threadB.notifyAll();
ThreadLocal
ThreadLocal中存儲(chǔ)的鍵值對綁定到線程,當(dāng)其中的值不再使用時(shí)需要置空以便垃圾回收。可以用于方法調(diào)用計(jì)時(shí)。