日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Concurrent包详解及使用场景

發布時間:2024/4/24 综合教程 48 生活家
生活随笔 收集整理的這篇文章主要介紹了 Concurrent包详解及使用场景 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Concurrent包是jdk1.5所提供的一個針對高并發進行編程的包。

1.阻塞式隊列 - BlockingQueue

遵循先進先出(FIFO)的原則。阻塞式隊列本身使用的時候是需要指定界限的。

在生產者消費者模型中,生產數據和消費數據的速率不一致,如果生產數據速度快一些,消費(處理)不過來,就會導致數據丟失。這時候我們就可以應用上阻塞隊列來解決這個問題。

ArrayBlockingQueue - 阻塞式順序隊列

底層是基于數組來進行存儲,使用的時候需要指定一個容量,容量指定之后不可改變。--- 生產 - 消費模型

public static void main(String[] args) throws InterruptedException {

// 這個隊列在創建的時候需要指定容量,容量在指定之后不可變
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);

// 添加隊列
queue.add("a");
queue.add("b");
queue.add("c");
queue.add("d");
queue.add("e");

// 如果隊列已滿,則拋出異常 - IllegalStateException
// queue.add("a");
// 返回值標記元素是否成功添加到隊列里面
// 如果隊列已滿,則返回false
// boolean b = queue.offer("b");
// System.out.println(b);
// 如果隊列已滿,會產生阻塞 --- 直到這個隊列中有元素被取出,才會放開阻塞
// queue.put("c");

// 定時阻塞
// 在3s之內如果有元素被取出,那么元素就會添加到隊列中
// 如果3s之后隊列依然是滿的,那么返回false表示添加失敗
boolean b = queue.offer("d", 3000, TimeUnit.MILLISECONDS);
System.out.println(b);
System.out.println(queue);
}

LinkedBlockingQueue - 阻塞式鏈式隊列

底層是基于鏈表(節點)來進行數據的存儲。在使用的時候可以指定初始容量,也可以不指定。

如果指定了容量,就以指定的容量為準來進行存儲;

如果不指定容量,那么默認容量是 Integer.MAX_VALUE -> 231- 1。如果不指定容量,一般認為這個容量是無限的。

PriorityBlockingQueue - 具有優先級的阻塞式隊列

如果不指定容量,默認容量是11.如果將元素取出,那么會對元素進行自然排序 --- 要求存儲的對象所對應的類必須實現Comparable,重寫compareTo方法,講比較規則寫到方法中;如果進行迭代遍歷,那么不保證排序。

SynchronousQueue - 同步隊列

只允許存儲1個元素。

2.并發映射 - ConcurrentMap

HashMap - 底層依靠數組+鏈表存儲的數據

默認初始容量是16,默認加載因子是0.75f,默認擴容每次增加一倍。本身是一個異步式線程不安全的映射

Hashtable - 同步式線程安全的映射

對外提供的方法都是同步方法

ConcurrentHashMap - 異步式線程安全的映射

在jdk1.8之前,采用分段(分桶)鎖, 分段鎖采用的是讀寫鎖機制(讀鎖:允許多個線程讀,但是不允許線程寫;寫鎖:允許一個線程寫,但是不允許線程讀);jdk1.8不再采用鎖機制,而是CAS(Compare and Swap)算法, 減小了鎖的開銷;如果一個桶中的元素個數超過了8個,那么會將這個桶的鏈表扭轉成一棵紅黑樹(自平衡二叉查找樹)結構。

ConcurrentNavigableMap - 并發導航映射

本身是一個接口,所以更多的是使用實現類

ConcurrentSkipListMap - 并發跳躍表映射

跳躍表:為了提高查詢效率所產生的一種數據結構

跳躍表是典型的以空間換時間的產物。

跳躍表的時間復雜度是O(logn)

如果跳躍表中插入新的元素,新的元素是否往上提取,遵循“拋硬幣”原則 --- 1/2原則

只要保證這個節點有一半的概率被提取就可以

跳躍表適合大量查詢而不增刪的場景

CountDownLatch - 閉鎖 - 線程減鎖

對線程neg進行計數,當計數歸零的時候會開放阻塞線程繼續往下執行

public class CountDownLatchDemo {

public static void main(String[] args) throws InterruptedException {

CountDownLatch cdl = new CountDownLatch(5);

new Thread(new Teacher(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();

// 表示讓線程阻塞,直到計數歸零的時候阻塞才能放開
cdl.await();
System.out.println("考試結束~~~");
}
}

class Student implements Runnable {

private CountDownLatch cdl;

public Student(CountDownLatch cdl) {
this.cdl = cdl;
}

@Override
public void run() {

System.out.println("學生來到考場,準備考試~~~");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("學生交卷離開考場");

// 計數-1
cdl.countDown();
}
}

class Teacher implements Runnable {

private CountDownLatch cdl;

public Teacher(CountDownLatch cdl) {
this.cdl = cdl;
}

@Override
public void run() {

System.out.println("老師來到考場,準備考試~~~");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("老師收卷離開了考場~~~");

cdl.countDown();
}
}

原文地址:https://www.cnblogs.com/chuijingjing/p/10072912.html

總結

以上是生活随笔為你收集整理的Concurrent包详解及使用场景的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。