純粹是個人學習總結,如有不對的地方請吐槽。
創建線程的三種方式:
繼承Thread類
public class MyThread extends Thread {
@Override
public void run() {
//需要在線程中運行的代碼
}
}
實現Runnable接口
public class MyThread implements Runnable {
@Override
public void run() {
//需要在線程中運行的代碼
}
}
匿名類部類
new Thread(new Runnable() {
@Override
public void run() {
}
});
new Thread(){
@Override
public void run() {
}
};
總結
采用實現Runnable、Callable接口的方式創見多線程時,優勢是:
線程類只是實現了Runnable接口或Callable接口,還可以繼承其他類。
在這種方式下,多個線程可以共享同一個target對象,所以非常適合多個相同線程來處理同一份資源的情況,從而可以將CPU、代碼和數據分開,形成清晰的模型,較好地體現了面向對象的思想。
劣勢是:
編程稍微復雜,如果要訪問當前線程,則必須使用Thread.currentThread()方法。
使用繼承Thread類的方式創建多線程時優勢是:
編寫簡單,如果需要訪問當前線程,則無需使用Thread.currentThread()方法,直接使用this即可獲得當前線程。
劣勢是:
線程類已經繼承了Thread類,所以不能再繼承其他父類。
線程的幾種狀態
●就緒(Runnable):線程準備運行,不一定立馬就能開始執行。
●運行中(Running):進程正在執行線程的代碼。
●等待中(Waiting):線程處于阻塞的狀態,等待外部的處理結束。
●睡眠中(Sleeping):線程被強制睡眠。
●I/O阻塞(Blocked on I/O):等待I/O操作完成。
●同步阻塞(Blocked on Synchronization):等待獲取鎖。
●死亡(Dead):線程完成了執行。
線程的方法、屬性
1)優先級(priority)
每個類都有自己的優先級,一般property用1-10的整數表示,默認優先級是5,優先級最高是10;優先級高的線程并不一定比優先級低的線程執行的機會高,只是執行的機率高;默認一個線程的優先級和創建他的線程優先級相同;
2)Thread.sleep()/sleep(long millis)
當前線程睡眠/millis的時間(millis指定睡眠時間是其最小的不執行時間,因為sleep(millis)休眠到達后,無法保證會被JVM立即調度);sleep()是一個靜態方法(static method) ,所以他不會停止其他的線程也處于休眠狀態;線程sleep()時不會失去擁有的對象鎖。 作用:保持對象鎖,讓出CPU,調用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留一定的時間給其他線程執行的機會;
3)Thread.yield()
讓出CPU的使用權,給其他線程執行機會、讓同等優先權的線程運行(但并不保證當前線程會被JVM再次調度、使該線程重新進入Running狀態),如果沒有同等優先權的線程,那么yield()方法將不會起作用。
4)thread.join()
使用該方法的線程會在此之間執行完畢后再往下繼續執行。
5)object.wait()
當一個線程執行到wait()方法時,他就進入到一個和該對象相關的等待池(Waiting Pool)中,同時失去了對象的機鎖—暫時的,wait后還要返還對象鎖。當前線程必須擁有當前對象的鎖,如果當前線程不是此鎖的擁有者,會拋出IllegalMonitorStateException異常,所以wait()必須在synchronized block中調用。
6)object.notify()/notifyAll()
喚醒在當前對象等待池中等待的第一個線程/所有線程。notify()/notifyAll()也必須擁有相同對象鎖,否則也會拋出IllegalMonitorStateException異常。
7)Synchronizing Block
Synchronized Block/方法控制對類成員變量的訪問;Java中的每一個對象都有唯一的一個內置的鎖,每個Synchronized Block/方法只有持有調用該方法被鎖定對象的鎖才可以訪問,否則所屬線程阻塞;機鎖具有獨占性、一旦被一個Thread持有,其他的Thread就不能再擁有(不能訪問其他同步方法),方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。
原文地址丟失