1.什麼是同步容器類?
同步容器有 vector,hashtable等,他們的實現方式是:封裝類的狀態,對每個公有方法都使用同步,使得每次只有一個線程能訪問容器的狀態。
對於同步容器每個方法來說,它是線程安全的
但是在客戶端代碼中,一些複合操作仍然會出現併發性問題。
常見的複合操作:
迭代
跳轉
條件運算 若沒有則添加
解決方法:
在客戶端對容器加鎖。
帶來的另外一個問題:
性能,長時間的對容器加鎖會降低程序的可伸縮性,持有鎖的時間越長,鎖上的競爭就可能更加激烈。
2.什麼是併發容器?
併發容器是用來替代同步容器,可以極大的提高伸縮性並降低風險。
常見的
ConcurrentHashMap
使用的顆粒度更細的加鎖機制,分段鎖
size和is empty的值變成了一個估算值
但是get put containkey 和remove的性能更加優化
CopyOnWriteArrayList
只要正確發佈一個事實不可變的對象,在訪問該對象時就不再需要進一步的同步
3.同步工具類
信號量, 柵欄, 閉鎖
閉鎖
作用:可以延遲線程的進度直到其達到中止狀態。
CountDownLatch
所有的線程都必須等待CountDownLatch的計數變成0的時候纔會同時執行.
FutureTask
異步任務,調用後繼續執行下一個代碼,待需要用到結果時通過get方法來獲取結果
Semaphore
信號量,用來控制同時訪問某個特定資源的操作數量,
在實際的應用層中也可以用信號量來實現限流
如:
public class SemaphoreTest {
private static ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 20; i++) {
Runnable runnable = () -> {
try {
semaphore.acquire();
Thread.sleep((long) Math.random());
semaphore.release();
System.out.println("剩餘許可:"+semaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
};
executorService.submit(runnable);
}
executorService.shutdown();
}
}
柵欄
類似於閉鎖,區別在於,所有線程必須同時到達柵欄位置,才能繼續執行。閉鎖用於等待事件,柵欄用於等待其他線程。
exchanger 兩方柵欄,各方在柵欄位置上交換數據。