一:ThreadLocal<T> local = new ThreadLocal<>();
如:
ThreadLocal<Long> startTime = new ThreadLocal<>();
使用:
startTime.set(System.currentTimeMillis());
System.currentTimeMillis() - startTime.get(); 還有remove()方法。
解析:使用 threadLocal 設置變量,此時該變量僅僅會在當前線程中進行保存刪除操作,不會影響到其他線程
二:併發集合容器使用之:CopyOnWriteArrayList();
實現:
this.hmilyParticipants = Lists.newCopyOnWriteArrayList();
認識:CopyOnWriteArrayList 是一個安全的併發 arrayList集合,特性:讀時無鎖,寫時有鎖,適用於讀操作遠遠大於寫操作的情形。是一種讀寫分離的併發策略。底層原理:首先將當前容器複製一份,然後在新副本上執行寫操作,結束之後再將原容器的引用指向新容器。
缺點:1.首先佔用內存大,每次都要生成一份新的副本,數據量大時,對內存影響較大。2、無法保證實時性,在寫操作過程中,不會阻塞但是讀取到的是老容器的數據。3、大量寫操作時性能極差。
三:如何安全停止一個線程
public class BestPractice extends Thread {
private volatile boolean finished = false; // ① volatile條件變量
public void stopMe() {
finished = true; // ② 發出停止信號
}
@Override
public void run() {
while (!finished) { // ③ 檢測條件變量
// do dirty work // ④業務代碼
}
}
}
使用信號量停止線程是最好的辦法,其次就是Thread.currentThread().interrupt();然後判斷 Thread.currentThread.isInterrupted()進行判斷 如:while(!Thread.currentThread.isInterrupted()){ break; }
四:爲什麼用BlockingQueue實現生產者消費者:
首先併發集合容器包括:ConcurrentLinkedQueue(高性能的併發隊列,使用無鎖實現,基於樂觀鎖)、CopyOnWriteArrayList(讀寫分離的鎖策略) 以及 BlockingQueue(包括 ArrayBlockingQueue、LinkedBlockingQueue),在實踐中一直是使用阻塞隊列 BlockingQueue實現生產者消費者,究其原因就在於 BlockingQueue隊列中 的存放put()以及獲取 take()都是阻塞的,如:包含 notEmpty 和 notFull 兩把鎖,如果符合條件就會讓對應的鎖進行 等待 如: notEmpty.awit() 如果察覺到條件變化就調用 notEmpty.notify() 喚醒,這樣就不需要通過定時任務定時去判斷、刷新數據,因此使用 blockingQueue作爲生產者消費者。而因爲是加鎖的,所以性能不是很好,這時候 disruptor 這個無鎖的生產者消費者框架有了用武之地。