Java多線程
線程可以理解為是在進程中獨立運行的子任務。
Java多線程
使用方法
Java中實現多線程主要有以下兩種方法:
- 繼承Thread,而后實例化該對象調用start()即啟動了新線程;
- 實現Runnable,通過
new Thread(Runnable run)
實例化該線程,而后調用start();
常用方法
Thread.currentThread()
靜態方法,獲取當前線程對象;isAlive()
判斷線程是否處於活動狀態,即線程已啟動且尚未終止;Thread.sleep(long )
在指定的毫秒數內讓當前線程休眠,需要catch InterruptedException
;Thread.interrupted()
判斷該線程是否中斷,執行后將清除中斷標志;isInterrupted()
測試線程是否已經中斷;suspend() resume() stop()
暫停、開始和結束線程,不應該使用。暫停方法不會釋放資源;yield()
該線程放棄當前CPU資源,放棄后馬上進行CPU競爭;setPriority()
設置線程優先級,1~10,越大優先級越高;- 優先級具有繼承性,即子線程有父線程的優先級;
- 高優先級的線程總是大部分先執行完,但不代表高優先級將全部先完成;
- 優先級較高的不一定每一次都先執行完,具有隨機性;
- 具體的與OS相關;
setDaemon()
設置守護線程,當進程不存在非守護線程時則守護線程將銷魂而后進程銷毀;
停止線程
停止線程有一下方法:
- 使用退出標志,在線程中檢查標志判斷是否退出。
- 使用stop方法強制終止線程,該方法可能導致線程不安全,不要使用。
- 使用interrupt方法中斷線程,其原理就是第1條,只是Thread對其進行了封裝。
- 使用interrupt中斷結合異常退出線程,在線程中當讀到中斷標志已經設置,可在此時拋出
InterruptedException
使線程退出。 - 在sleep狀態下如果該線程被中斷,則將進入
catch InterruptedException
同時將清除中斷標志。 - 使用interrupte與return實現停止線程,但是仍然建議使用異常退出,這樣可以保留中斷異常使線程停止異常得到傳播。
同步
非線程安全:存在多個線程對同一個對象中的實例變量進行並發訪問控制由此導致的數據臟讀;
- 方法內的局部變量和實例內的私有變量(不存在get/set)均不能被外部訪問,因此是線程安全的;
synchronized
- synchronized取得的是對象鎖而非方法或代碼塊的鎖;
- synchronized聲明的方法一定是排隊運行的,而且只有共享資源的讀寫才需要使用其進行同步;
- synchronized聲明的非靜態方法其獲取的鎖是該實例對象的鎖;
- synchronized聲明的靜態方法獲取的鎖是該類對象(永久代中類對象)的鎖;
- synchronized聲明的代碼塊獲取的鎖則是括號里聲明的對象的鎖;
- synchronized未聲明的方法對其調用時不需要考慮鎖的問題,因此不會有synchronized方法或代碼塊沖突;
- synchronized支持鎖重入(同一線程多次獲取同一個鎖);
- 同步方法或代碼塊中出現異常則其所持鎖將自動釋放;
- 方法的同步不具有繼承性;
- 同步方法或代碼塊是否沖突只看兩者鎖持有的鎖是否是同一個;
- synchronized聲明的非靜態方法與synchronized(this)的代碼塊使用的鎖都是對象本身;
- 由於String的常量池可能使相同字符串指向同一個對象,因此不要使用String作為synchronized代碼塊的對象監視器;
- synchronized方法或代碼塊內的變量也有可見性;
volatile
- volatile是使變量擁有可見性;
- volatile修飾的變量在使用時並非從工作內存獲取而是都從主內存中獲取;
- volatile修飾的變量在修改時其修改結果將直接寫入到主內存;
- 多線程訪問volatile變量不會阻塞,但是不保證變量的原子性;
---恢復內容結束---