最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java并發(fā)之Condition

 更新時(shí)間:2020年06月05日 10:06:07   作者:數(shù)月亮  
這篇文章主要介紹了Java并發(fā)編程之Condition,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

在使用Lock之前,我們使用的最多的同步方式應(yīng)該是synchronized關(guān)鍵字來(lái)實(shí)現(xiàn)同步方式了。配合Object的wait()、notify()系列方法可以實(shí)現(xiàn)等待/通知模式。Condition接口也提供了類似Object的監(jiān)視器方法,與Lock配合可以實(shí)現(xiàn)等待/通知模式,但是這兩者在使用方式以及功能特性上還是有差別的。Object和Condition接口的一些對(duì)比。摘自《Java并發(fā)編程的藝術(shù)》

一、Condition接口介紹和示例

        首先我們需要明白condition對(duì)象是依賴于lock對(duì)象的,意思就是說(shuō)condition對(duì)象需要通過(guò)lock對(duì)象進(jìn)行創(chuàng)建出來(lái)(調(diào)用Lock對(duì)象的newCondition()方法)。consition的使用方式非常的簡(jiǎn)單。但是需要注意在調(diào)用方法前獲取鎖。

package com.ydl.test.juc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionUseCase {

  public Lock lock = new ReentrantLock();
  public Condition condition = lock.newCondition();

  public static void main(String[] args) {
    ConditionUseCase useCase = new ConditionUseCase();
    ExecutorService executorService = Executors.newFixedThreadPool (2);
    executorService.execute(new Runnable() {
      @Override
      public void run() {
        useCase.conditionWait();
      }
    });
    executorService.execute(new Runnable() {
      @Override
      public void run() {
        useCase.conditionSignal();
      }
    });
  }

  public void conditionWait() {
    lock.lock();
    try {
      System.out.println(Thread.currentThread().getName() + "拿到鎖了");
      System.out.println(Thread.currentThread().getName() + "等待信號(hào)");
      condition.await();
      System.out.println(Thread.currentThread().getName() + "拿到信號(hào)");
    }catch (Exception e){

    }finally {
      lock.unlock();
    }
  }
  public void conditionSignal() {
    lock.lock();
    try {
      Thread.sleep(5000);
      System.out.println(Thread.currentThread().getName() + "拿到鎖了");
      condition.signal();
      System.out.println(Thread.currentThread().getName() + "發(fā)出信號(hào)");
    }catch (Exception e){

    }finally {
      lock.unlock();
    }
  }

}

pool-1-thread-1拿到鎖了
pool-1-thread-1等待信號(hào)
pool-1-thread-2拿到鎖了
pool-1-thread-2發(fā)出信號(hào)
pool-1-thread-1拿到信號(hào)

如示例所示,一般都會(huì)將Condition對(duì)象作為成員變量。當(dāng)調(diào)用await()方法后,當(dāng)前線程會(huì)釋放鎖并在此等待,而其他線程調(diào)用Condition對(duì)象的signal()方法,通知當(dāng)前線程后,當(dāng)前線程才從await()方法返回,并且在返回前已經(jīng)獲取了鎖。

二、Condition接口常用方法

        condition可以通俗的理解為條件隊(duì)列。當(dāng)一個(gè)線程在調(diào)用了await方法以后,直到線程等待的某個(gè)條件為真的時(shí)候才會(huì)被喚醒。這種方式為線程提供了更加簡(jiǎn)單的等待/通知模式。Condition必須要配合鎖一起使用,因?yàn)閷?duì)共享狀態(tài)變量的訪問(wèn)發(fā)生在多線程環(huán)境下。一個(gè)Condition的實(shí)例必須與一個(gè)Lock綁定,因此Condition一般都是作為L(zhǎng)ock的內(nèi)部實(shí)現(xiàn)。

await() :造成當(dāng)前線程在接到信號(hào)或被中斷之前一直處于等待狀態(tài)。

await(long time, TimeUnit unit) :造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定等待時(shí)間之前一直處于等待狀態(tài)。

awaitNanos(long nanosTimeout) :造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定等待時(shí)間之前一直處于等待狀態(tài)。返回值表示剩余時(shí)間,如果在nanosTimesout之前喚醒,那么返回值 = nanosTimeout - 消耗時(shí)間,如果返回值 <= 0 ,則可以認(rèn)定它已經(jīng)超時(shí)了。

awaitUninterruptibly() :造成當(dāng)前線程在接到信號(hào)之前一直處于等待狀態(tài)?!咀⒁猓涸摲椒▽?duì)中斷不敏感】。

awaitUntil(Date deadline) :造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定最后期限之前一直處于等待狀態(tài)。如果沒(méi)有到指定時(shí)間就被通知,則返回true,否則表示到了指定時(shí)間,返回返回false。

signal() :?jiǎn)拘岩粋€(gè)等待線程。該線程從等待方法返回前必須獲得與Condition相關(guān)的鎖。

signal()All :?jiǎn)拘阉械却€程。能夠從等待方法返回的線程必須獲得與Condition相關(guān)的鎖。

三、Condition接口原理簡(jiǎn)單解析

        Condition是AQS的內(nèi)部類。每個(gè)Condition對(duì)象都包含一個(gè)隊(duì)列(等待隊(duì)列)。等待隊(duì)列是一個(gè)FIFO的隊(duì)列,在隊(duì)列中的每個(gè)節(jié)點(diǎn)都包含了一個(gè)線程引用,該線程就是在Condition對(duì)象上等待的線程,如果一個(gè)線程調(diào)用了Condition.await()方法,那么該線程將會(huì)釋放鎖、構(gòu)造成節(jié)點(diǎn)加入等待隊(duì)列并進(jìn)入等待狀態(tài)。等待隊(duì)列的基本結(jié)構(gòu)如下所示。

等待分為首節(jié)點(diǎn)和尾節(jié)點(diǎn)。當(dāng)一個(gè)線程調(diào)用Condition.await()方法,將會(huì)以當(dāng)前線程構(gòu)造節(jié)點(diǎn),并將節(jié)點(diǎn)從尾部加入等待隊(duì)列。新增節(jié)點(diǎn)就是將尾部節(jié)點(diǎn)指向新增的節(jié)點(diǎn)。節(jié)點(diǎn)引用更新本來(lái)就是在獲取鎖以后的操作,所以不需要CAS保證。同時(shí)也是線程安全的操作。

       3.2、等待

當(dāng)線程調(diào)用了await方法以后。線程就作為隊(duì)列中的一個(gè)節(jié)點(diǎn)被加入到等待隊(duì)列中去了。同時(shí)會(huì)釋放鎖的擁有。當(dāng)從await方法返回的時(shí)候。一定會(huì)獲取condition相關(guān)聯(lián)的鎖。當(dāng)?shù)却?duì)列中的節(jié)點(diǎn)被喚醒的時(shí)候,則喚醒節(jié)點(diǎn)的線程開(kāi)始嘗試獲取同步狀態(tài)。如果不是通過(guò) 其他線程調(diào)用Condition.signal()方法喚醒,而是對(duì)等待線程進(jìn)行中斷,則會(huì)拋出InterruptedException異常信息。

       3.3、通知

調(diào)用Condition的signal()方法,將會(huì)喚醒在等待隊(duì)列中等待最長(zhǎng)時(shí)間的節(jié)點(diǎn)(條件隊(duì)列里的首節(jié)點(diǎn)),在喚醒節(jié)點(diǎn)前,會(huì)將節(jié)點(diǎn)移到同步隊(duì)列中。當(dāng)前線程加入到等待隊(duì)列中如圖所示:

在調(diào)用signal()方法之前必須先判斷是否獲取到了鎖。接著獲取等待隊(duì)列的首節(jié)點(diǎn),將其移動(dòng)到同步隊(duì)列并且利用LockSupport喚醒節(jié)點(diǎn)中的線程。節(jié)點(diǎn)從等待隊(duì)列移動(dòng)到同步隊(duì)列如下圖所示:

被喚醒的線程將從await方法中的while循環(huán)中退出。隨后加入到同步狀態(tài)的競(jìng)爭(zhēng)當(dāng)中去。成功獲取到競(jìng)爭(zhēng)的線程則會(huì)返回到await方法之前的狀態(tài)。

四、總結(jié)

      調(diào)用await方法后,將當(dāng)前線程加入Condition等待隊(duì)列中。當(dāng)前線程釋放鎖。否則別的線程就無(wú)法拿到鎖而發(fā)生死鎖。自旋(while)掛起,不斷檢測(cè)節(jié)點(diǎn)是否在同步隊(duì)列中了,如果是則嘗試獲取鎖,否則掛起。當(dāng)線程被signal方法喚醒,被喚醒的線程將從await()方法中的while循環(huán)中退出來(lái),然后調(diào)用acquireQueued()方法競(jìng)爭(zhēng)同步狀態(tài)。

五、利用Condition實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BoundedQueue {

  private LinkedList<Object> buffer;  //生產(chǎn)者容器
  private int maxSize ;      //容器最大值是多少
  private Lock lock;
  private Condition fullCondition;
  private Condition notFullCondition;
  BoundedQueue(int maxSize){
    this.maxSize = maxSize;
    buffer = new LinkedList<Object>();
    lock = new ReentrantLock();
    fullCondition = lock.newCondition();
    notFullCondition = lock.newCondition();
  }

  /**
   * 生產(chǎn)者
   * @param obj
   * @throws InterruptedException
   */
  public void put(Object obj) throws InterruptedException {
    lock.lock();  //獲取鎖
    try {
      while (maxSize == buffer.size()){
        notFullCondition.await();    //滿了,添加的線程進(jìn)入等待狀態(tài)
      }
      buffer.add(obj);
      fullCondition.signal(); //通知
    } finally {
      lock.unlock();
    }
  }

  /**
   * 消費(fèi)者
   * @return
   * @throws InterruptedException
   */
  public Object get() throws InterruptedException {
    Object obj;
    lock.lock();
    try {
      while (buffer.size() == 0){ //隊(duì)列中沒(méi)有數(shù)據(jù)了 線程進(jìn)入等待狀態(tài)
        fullCondition.await();
      }
      obj = buffer.poll();
      notFullCondition.signal(); //通知
    } finally {
      lock.unlock();
    }
    return obj;
  }

}

以上就是詳解Java并發(fā)之Condition的詳細(xì)內(nèi)容,更多關(guān)于Java并發(fā)Condition的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Netty中的DelimiterBasedFrameDecoder使用方法詳解

    Netty中的DelimiterBasedFrameDecoder使用方法詳解

    這篇文章主要介紹了Netty中的DelimiterBasedFrameDecoder使用方法詳解,DelimiterBasedFrameDecoder與LineBasedFrameDecoder類似,只不過(guò)更加通用,允許我們指定任意特殊字符作為分隔符,我們還可以同時(shí)指定多個(gè)分隔符,需要的朋友可以參考下
    2023-12-12
  • SpringBoot優(yōu)化接口響應(yīng)時(shí)間的九個(gè)技巧

    SpringBoot優(yōu)化接口響應(yīng)時(shí)間的九個(gè)技巧

    在實(shí)際開(kāi)發(fā)中,提升接口響應(yīng)速度是一件挺重要的事,特別是在面臨大量用戶請(qǐng)求的時(shí)候,本文為大家整理了9個(gè)SpringBoot優(yōu)化接口響應(yīng)時(shí)間的技巧,希望對(duì)大家有所幫助
    2024-01-01
  • 手工搭建Servlet實(shí)現(xiàn)

    手工搭建Servlet實(shí)現(xiàn)

    現(xiàn)在作為一個(gè)Java程序員,我們已經(jīng)習(xí)慣了使用IDE和Web框架進(jìn)行開(kāi)發(fā),IDE幫助我們做了編譯、打包的工作。Spring框架則幫助我們實(shí)現(xiàn)了Servlet接口,并把Servlet容器注冊(cè)到了Web容器中。本文主要介紹了Servlet手工搭建,感興趣的可以了解一下
    2021-07-07
  • mybatis插入數(shù)據(jù)后返回自增主鍵ID的兩種實(shí)現(xiàn)方式

    mybatis插入數(shù)據(jù)后返回自增主鍵ID的兩種實(shí)現(xiàn)方式

    這篇文章主要介紹了mybatis插入數(shù)據(jù)后返回自增主鍵ID的兩種實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java源碼跟蹤閱讀技巧【值得收藏】

    Java源碼跟蹤閱讀技巧【值得收藏】

    今天跟大家分享一下我平時(shí)閱讀源碼的幾個(gè)小技巧,對(duì)于閱讀Java中間件如Spring、Dubbo等框架源碼的同學(xué)有一定幫助。本文基于Eclipse IDE,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn)代碼

    IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn)代碼

    這篇文章主要介紹了IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • startActivityForResult和setResult案例詳解

    startActivityForResult和setResult案例詳解

    這篇文章主要介紹了startActivityForResult和setResult案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • IDEA中springboot的熱加載thymeleaf靜態(tài)html頁(yè)面的方法

    IDEA中springboot的熱加載thymeleaf靜態(tài)html頁(yè)面的方法

    這篇文章主要介紹了IDEA中springboot的熱加載thymeleaf靜態(tài)html頁(yè)面的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Java生成驗(yàn)證碼

    Java生成驗(yàn)證碼

    本文介紹了Java生成驗(yàn)證碼的流程與方法。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • 詳解Java程序讀取properties配置文件的方法

    詳解Java程序讀取properties配置文件的方法

    這篇文章主要介紹了Java讀取properties配置文件的方法講解,properties可以被看作是Java世界的ini,Java中有Properties可以操作它,需要的朋友可以參考下
    2016-04-04

最新評(píng)論

平泉县| 平阳县| 云浮市| 温泉县| 高唐县| 二连浩特市| 南丰县| 诸暨市| 洛浦县| 紫金县| 绥宁县| 温州市| 怀柔区| 山阳县| 永康市| 长子县| 宁远县| 游戏| 保康县| 崇礼县| 汉川市| 阳江市| 绵竹市| 黔东| 沭阳县| 安阳市| 拉萨市| 福泉市| 苗栗县| 太保市| 大余县| 荔浦县| 湖口县| 黄山市| 建昌县| 甘南县| 团风县| 且末县| 舟曲县| 文昌市| 海阳市|