Java執行緒及執行緒池
阿新 • • 發佈:2018-12-25
Java執行緒及執行緒池
什麼是執行緒安全
- 多個任務同時執行,不會出問題
- 類的全域性變數和靜態變數在多個執行緒同時訪問時,如果只有讀為執行緒安全,如果有寫,則可能出現執行緒不安全
建立執行緒的3種方式
- 繼承Thread類,並重寫run()方法
- 實現Runnable介面,並實現run()方法
- 實現Callable介面,有返回值
Runnable介面和Callable介面的區別
一個有返回值,一個沒有
wait方法和sleep方法的區別
wait會讓出執行緒鎖,讓別的執行緒先執行,sleep不會
介紹下CAS(無鎖技術),什麼是悲觀鎖和樂觀鎖
- CAS是CPU的指令,將比較和轉換做為一個原子操作,如果比較的結果是預期結果就是轉換,否則不做任何操作。但是,這會出現另一個問題:ABA,即會出現在CAS執行時,雖然比較結果是成功的,但不知道這個結果是否已經被改過新值又改回原值,故可以用AtomicStampedReference,在初始化時新增一個版本號,比較時也比較版本號來保證沒有被修改過
- 悲觀鎖:synchronized鎖,即在執行多執行緒程式碼時,會出現競爭問題,先給這段程式碼上鎖
- 樂觀鎖:CAS鎖,操作為原子性,如果失敗,通過死迴圈來重複執行,直到成功達到預期
volatile關鍵字的作用和原理
volatile是輕量級的同步鎖,但不是原子性的,因為這個關鍵字是在主記憶體中,每個得到鎖的執行緒在執行時,會先從主記憶體中把這個值放到自己的執行緒工作記憶體中,因此會出現不準確的同步。同時,這個關鍵字也會防止指令重排,保證化修飾的變數不會出現指令重排。
什麼是ThreadLocal
- ThreadLocal是Thread中的一個變數,可以叫做執行緒本地變數,用來儲存執行緒中的一個物件,如在多執行緒環境中,每個執行緒有session、connection等,只要有任務過來,就可以立即用自己執行緒ThreadLoacl中的儲存的物件進行操作,不必從主執行緒或者主記憶體中取資料,即中空間換取時間,來提高執行速度。
- 在儲存ThreadLoacl中使用的是類似HashMap的一個ThreadLocalMap,對執行緒隔離後,每個執行緒儲存物件的一個執行緒私有變數。
建立執行緒池的4種方式
- Executors.newCachedThreadPool():快取執行緒池,沒有初始數,最大為Integer.MAX
- Executors.newFixedThreadPool(2):固定數執行緒池,初始值即為最大值,有一個連結串列佇列
- Executors.newSingleThreadExecutor():單執行緒池,有一個連結串列佇列
- Executors.newWorkStealingPool():
執行緒池啟動的引數解釋
new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
- 初始個數:執行緒池中的初始執行緒個數,必須大於0
- 最大個數:執行緒池中的最大執行緒個數,不能小於初始執行緒個數
- 存活時間:超過初始執行緒數後的那些執行緒存活時間
- 時間單位:3的時間單位
- 任務佇列:當執行緒池中的個數為最大執行緒數時,新來的任務將放到該佇列中
- 執行緒工廠:用來啟動執行緒,自定義執行緒名字等
- 滿隊策略:當佇列滿後,執行的異常策略
任務佇列:
- ArrayBlockingQueue:是一個基於陣列結構的有界阻塞佇列,按FIFO原則進行排序
- LinkedBlockingQueue:一個基於連結串列結構的阻塞佇列,吞吐量高於ArrayBlockingQueue。靜態工廠方法Executors.newFixedThreadPool()使用了這個佇列
- SynchronousQueue: 一個不儲存元素的阻塞佇列。每個插入操作必須等另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量高於LinkedBlockingQueue,靜態工廠方法Executors.newCachedThreadPool()使用了這個佇列
- PriorityBlockingQueue:一個具有優先順序的無限阻塞佇列。