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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 多线程 —— AQS 原理

發布時間:2025/3/12 java 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 多线程 —— AQS 原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

使用Condition實現生產者-消費者模型,并與wait和notify實現的效果相對比。

wait/notify模擬生產者-消費者

面試題:寫一個固定容量同步容器,擁有put和get方法,以及getCount方法能夠支持2個生產線程以及10個消費者線程的阻塞調用。

在《Effective Java》一書中提到:wait()方法()絕大多數情況下都是和while一起使用的。這是因為,當wait()執行完成后,會立刻釋放當前鎖,如果這時其他線程立刻獲得鎖并對變量進行操作,會出現數據不一致的情況,使用while可以確保數據不會出現不一致的情況。

public class ProducerConsumer1<T> {final private LinkedList<T> lists = new LinkedList<>();final private int MAX = 10;// 最多10個元素private int count = 0;public synchronized void put(T t) {while (lists.size() == this.MAX) {// 想想為什么用while而不是iftry {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}lists.add(t);count++;this.notifyAll();// 通知消費者線程進行消費}public synchronized T get() {T t = null;while (lists.size() == 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}t = lists.removeFirst();count--;this.notifyAll();// 通知生產者進行生產return t;}public static void main(String[] args) {ProducerConsumer1<String> c = new ProducerConsumer1<>();// 啟動消費者線程for (int i = 0; i < 10; i++) {new Thread(() -> {for (int j = 0; j < 5; j++) {System.out.println(c.get());}}, "c" + i).start();}try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 2; i++) {new Thread(() -> {for (int j = 0; j < 25; j++) {c.put(Thread.currentThread().getName() + " " + j);}}).start();}} }

Condition模擬生產者-消費者

使用Lock和Condition來實現類似需求時,可以更加精確的指定哪些線程被喚醒,這比notifyAll()效率更高一些。

將上面的程序代碼進行改寫:

public class ProducerConsumer2<T> {final private LinkedList<T> lists = new LinkedList<>();final private int MAX = 10;private int count = 0;private Lock lock = new ReentrantLock();private Condition producer = lock.newCondition();private Condition consumer = lock.newCondition();public void put(T t) {try {lock.lock();while (lists.size() == MAX) {producer.await();}lists.add(t);++count;consumer.signalAll(); // 通知消費者線程進行消費} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public T get() {T t = null;try {lock.lock();while (lists.size() == 0) {consumer.await();}t = lists.removeFirst();count--;producer.signalAll();// 通知生產者進行生產} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}return t;}public static void main(String[] args) {ProducerConsumer2<String> c = new ProducerConsumer2<>();// 啟動消費者線程for (int i = 0; i < 10; i++) {new Thread(() -> {for (int j = 0; j < 5; j++) {System.out.println(c.get());}}, "c" + i).start();}try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 2; i++) {new Thread(() -> {for (int j = 0; j < 25; j++) {c.put(Thread.currentThread().getName()+ " " + j);}}).start();}} }

鳴謝

《馬士兵老師高并發編程系列》

總結

以上是生活随笔為你收集整理的Java 多线程 —— AQS 原理的全部內容,希望文章能夠幫你解決所遇到的問題。

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