并發多線程
- 1.Java里面的線程和操作系統的線程一樣嗎?
- 2.Java的線程安全在三個方面體現:
- 3.保證數據一致性的方案
- 4.線程創建的方式
- 1)Thread類
- 2)Runnable接口
- 3)Callable接口和FutureTask
- 4)線程池(executor框架)
- 5.啟動一個線程
- 6.停止一個線程
- 7.Java線程的狀態有哪些
- 8.sleep()和wait()的區別
- 9.BLOCKED和WAITING的區別
- 10.WAITING進入RUNNABLE的核心機制
- 11.不同的線程之間如何通信
- 1)修改共享變量
- 2)等待通知機制
- 3)同步輔助類
- 4)計數信號量
- 12.停止一個線程
- 13.參考
1.Java里面的線程和操作系統的線程一樣嗎?
- Java程序創建的線程和操作系統的線程是一對一的,java底層會調用
pthread_create
來創建線程。
2.Java的線程安全在三個方面體現:
- 原子性:要么所有操作一起成功執行,要么一起失敗回滾(atomic包,synchronized關鍵字)。
- 可見性:保證線程對內存的修改可以及時被其他線程看見(synchronized關鍵字,volatile關鍵字)。
- 有序性:指程序執行順序符合預期,不會因為指令重排序后導致的亂序而出現錯誤(happens-before原則)。
3.保證數據一致性的方案
- 事務管理ACID
- 鎖機制(synchronized、ReentrantLock)
- CAS樂觀鎖
4.線程創建的方式
1)Thread類
- 繼承Thread類,重寫run(。
- 優點:編程簡單,訪問當前線程無需使用Thread.currentThread(), 直接使用this即可獲取當前線程。
- 缺點:繼承了Thread類就不能繼承其他父類。
2)Runnable接口
- 實現Runnable接口,重寫run(),然后將runnable對象作為參數傳遞給Thread類的構造器;
- 優點:
- 還可以繼承其他類。
- 多個線程共享同一個目標對象,適合多個相同線程來處理同一份資源的情況;
- 缺點:編程稍復雜,訪問當前對象需使用Thread.currentThread()方法。
3)Callable接口和FutureTask
- Callable接口類相較于Runnable,其有call()方法可以有返回值并且可以拋出異常。執行callable任務,需將它包裝進一個FutureTask,因為Thread類的構造器只接收Runnable參數,而FutureTask實現了Runnable接口。
- 缺點:編程復雜,訪問當前線程需調用Thread.currentThread()。
- 優點:
- 可以繼承其他類。
- 可以多個線程共享一個target對象,非常適合多線程處理同一份資源的情形。
4)線程池(executor框架)
- 可以使用executors類的靜態方法創建不同類型的線程池。
- 缺點:線程池增加了程序的復雜度。
- 優點:
- 線程重用,降低資源消耗。
- 提高響應速度,因為線程池的線程是預先創建好的。
- 提高系統穩定性,因為線程池可以限制并發線程數量。
- 支持任務隊列存儲待執行的任務,避免任務丟失。
5.啟動一個線程
- start(),線程會進入就緒狀態。
6.停止一個線程
- interrupt()修改中斷狀態標志位為true,run()中判斷當前程序狀態,中斷狀態就拋出InterruptedException異常。
- stop(),已棄用,清理工作不到位。
- return停止線程,interrupt()修改中斷狀態標志位為true后,run()中判斷當前程序狀態,中斷狀態就return。
7.Java線程的狀態有哪些
- 可以調用Thread中的getState()方法獲取當前線程狀態;
- NEW:初始化狀態;
- RUNNABLE:就緒狀態;
- BLOCKED:阻塞狀態,一般是獲取鎖的時候進行阻塞;
- WAITING:無時限等待狀態,一般是調用了wait()方法之后進行阻塞,正在等待另一個線程執行某些操作(如:notify());
- TIME_WAITING:有時限等待狀態,一般是調用了sleep()方法后進行阻塞;
- TERMINATED:終止狀態。
8.sleep()和wait()的區別
- 分類不同,sleep()是Thread類的靜態方法,wait()是Object類的實例方法,wait()必須通過對象來調用;
- sleep()線程不會釋放持有的對象鎖,但會主動讓出CPU時間片,時間結束自動進入就緒狀態,wait()線程會釋放持有的對象鎖,直到被其他線程調用相同對象的notify()喚醒;
- sleep()可以在任意位置調用,無需事先獲取鎖。Wait()必須在synchronized 代碼塊內調用,即要求線程需持有該對象的鎖,否則拋出異常
IllegalMonitorStateException
9.BLOCKED和WAITING的區別
- BLOCKED是鎖競爭失敗后被動觸發的狀態;WAITING是人為的主動觸發的狀態。
- BLOCKED的喚醒是其他線程釋放鎖后自動觸發的,WAITING必須通過特定方法來主動喚醒。
10.WAITING進入RUNNABLE的核心機制
- 外部事件觸發
- 資源可用性變化
11.不同的線程之間如何通信
1)修改共享變量
- volatile關鍵字用于保證變量的可見性。當一個變量被聲明為volatile時,它會保證該變量的寫操作會立即刷新到主內存中,而讀操作會從主內存中讀取最新的值。
2)等待通知機制
- Object類下的wait(),notify(),notifyAll();
- LockSupport類下的park(),unpark()方法,喚醒指定線程;
- Condition類下的await(),signal(),signalAll();
- ReentrantLock是Lock接口的一個實現類,condition通過lock.newCondition()方法創建;
- 可以創建多個等待集(存的是等待喚醒的對象),如:生產者、消費者,這樣可以實現生產者消費者互相喚醒。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LockConditionExample {private static final Lock lock = new ReentrantLock();private static final Condition condition = lock.newCondition();public static void main(String[] args) {......}
}
3)同步輔助類
4)計數信號量
12.停止一個線程
- 通過共享標志位主動終止(volatile關鍵字);
- 中斷機制(Thread.interrupt());
- 線程池的Future.cancel()停止線程(任務需通過線程池提交,且依賴中斷機制);
- 不可中斷,則關閉資源。
13.參考
https://www.xiaolincoding.com/interview/juc.html#%E5%A4%9A%E7%BA%BF%E7%A8%8B