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

Java使用Condition控制線程通信的方法實例詳解

 更新時間:2019年09月18日 08:40:08   作者:cakincqm  
這篇文章主要介紹了Java使用Condition控制線程通信的方法,結(jié)合實例形式分析了使用Condition類同步檢測控制線程通信的相關(guān)操作技巧,需要的朋友可以參考下

本文實例講述了Java使用Condition控制線程通信的方法。分享給大家供大家參考,具體如下:

一 點睛

當(dāng)使用Lock對象來保證同步時,Java提供了一個Condition類來保持協(xié)調(diào),使用Condition可以讓那些已經(jīng)得到Lock對象、卻無法繼續(xù)執(zhí)行的線程釋放Lock對象,Condtion對象也可以喚醒其他處于等待的線程。

Condition 將同步監(jiān)視鎖方法(wait、notify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與Lock對象組合使用,為每個對象提供多個等待集(wait-set)。在這種情況下,Lock 替代了同步方法或同步代碼塊,Condition替代了同步監(jiān)視鎖的功能。

Condition實例實質(zhì)上被綁定在一個Lock對象上。要獲得特定Lock實例的Condition實例,調(diào)用Lock對象newCondition()方法即可。Condtion類提供了如下三個方法:

await():類似于隱式同步監(jiān)視器上的wait()方法,導(dǎo)致當(dāng)前線程等待,直到其他線程調(diào)用該Condtion的signal ()方法或signalAll ()方法來喚醒該線程。該await方法有更多變體:long awaitNanos(long nanosTimeout)、void awaitUninterruptibly()、awaitUntil(Date deadline)等,可以完成更豐富的等待操作。

signal ():喚醒在此Lock對象上等待的單個線程。如果所有線程都在該Lock對象上等待,則會選擇喚醒其中一個線程。選擇是任意性的。只有當(dāng)前線程放棄對該Lock對象的鎖定后(使用await()方法),才可以執(zhí)行被喚醒的線程。

signalAll():喚醒在此Lock對象上等待的所有線程。只有當(dāng)前線程放棄對該該Lock對象的鎖定后,才可以執(zhí)行被喚醒的線程。

二 代碼

1 Account類

public class Account
{
   // 顯式定義Lock對象
   private final Lock lock = new ReentrantLock();
   // 獲得指定Lock對象對應(yīng)的Condition
   private final Condition cond = lock.newCondition();
   // 封裝賬戶編號、賬戶余額的兩個成員變量
   private String accountNo;
   private double balance;
   // 標(biāo)識賬戶中是否已有存款的旗標(biāo)
   private boolean flag = false;
   public Account(){}
   // 構(gòu)造器
   public Account(String accountNo , double balance)
   {
      this.accountNo = accountNo;
      this.balance = balance;
   }
   // accountNo的setter和getter方法
   public void setAccountNo(String accountNo)
   {
      this.accountNo = accountNo;
   }
   public String getAccountNo()
   {
      return this.accountNo;
   }
   // 因此賬戶余額不允許隨便修改,所以只為balance提供getter方法,
   public double getBalance()
   {
      return this.balance;
   }
   public void draw(double drawAmount)
   {
      // 加鎖
      lock.lock();
      try
      {
        // 如果flag為假,表明賬戶中還沒有人存錢進(jìn)去,取錢方法阻塞
        if (!flag)
        {
           cond.await();
        }
        else
        {
           // 執(zhí)行取錢
           System.out.println(Thread.currentThread().getName()
              + " 取錢:" + drawAmount);
           balance -= drawAmount;
           System.out.println("賬戶余額為:" + balance);
           // 將標(biāo)識賬戶是否已有存款的旗標(biāo)設(shè)為false。
           flag = false;
           // 喚醒其他線程
           cond.signalAll();
        }
      }
      catch (InterruptedException ex)
      {
        ex.printStackTrace();
      }
      // 使用finally塊來釋放鎖
      finally
      {
        lock.unlock();
      }
   }
   public void deposit(double depositAmount)
   {
      lock.lock();
      try
      {
        // 如果flag為真,表明賬戶中已有人存錢進(jìn)去,則存錢方法阻塞
        if (flag)       // ①
        {
           cond.await();
        }
        else
        {
           // 執(zhí)行存款
           System.out.println(Thread.currentThread().getName()
              + " 存款:" + depositAmount);
           balance += depositAmount;
           System.out.println("賬戶余額為:" + balance);
           // 將表示賬戶是否已有存款的旗標(biāo)設(shè)為true
           flag = true;
           // 喚醒其他線程
           cond.signalAll();
        }
      }
      catch (InterruptedException ex)
      {
        ex.printStackTrace();
      }
      // 使用finally塊來釋放鎖
      finally
      {
        lock.unlock();
      }
   }
   // 下面兩個方法根據(jù)accountNo來重寫hashCode()和equals()方法
   public int hashCode()
   {
      return accountNo.hashCode();
   }
   public boolean equals(Object obj)
   {
      if(this == obj)
        return true;
      if (obj !=null
        && obj.getClass() == Account.class)
      {
        Account target = (Account)obj;
        return target.getAccountNo().equals(accountNo);
      }
      return false;
   }
}

2 DrawThread線程類

public class DrawThread extends Thread
{
   // 模擬用戶賬戶
   private Account account;
   // 當(dāng)前取錢線程所希望取的錢數(shù)
   private double drawAmount;
   public DrawThread(String name , Account account
      , double drawAmount)
   {
      super(name);
      this.account = account;
      this.drawAmount = drawAmount;
   }
   // 重復(fù)100次執(zhí)行取錢操作
   public void run()
   {
      for (int i = 0 ; i < 100 ; i++ )
      {
        account.draw(drawAmount);
      }
   }
}

3 DepositThread線程類

public class DepositThread extends Thread
{
   // 模擬用戶賬戶
   private Account account;
   // 當(dāng)前取錢線程所希望存款的錢數(shù)
   private double depositAmount;
   public DepositThread(String name , Account account
      , double depositAmount)
   {
      super(name);
      this.account = account;
      this.depositAmount = depositAmount;
   }
   // 重復(fù)100次執(zhí)行存款操作
   public void run()
   {
      for (int i = 0 ; i < 100 ; i++ )
      {
        account.deposit(depositAmount);
      }
   }
}

4 測試類

public class DrawTest
{
   public static void main(String[] args)
   {
      // 創(chuàng)建一個賬戶
      Account acct = new Account("1234567" , 0);
      new DrawThread("取錢者" , acct , 800).start();
      new DepositThread("存款者甲" , acct , 800).start();
      new DepositThread("存款者乙" , acct , 800).start();
      new DepositThread("存款者丙" , acct , 800).start();
   }
}

三 運行結(jié)果

......
存款者丙 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者甲 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者丙 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者甲 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者丙 存款:800.0
賬戶余額為:800.0
取錢者 取錢:800.0
賬戶余額為:0.0
存款者甲 存款:800.0
賬戶余額為:800.0

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java進(jìn)程與線程操作技巧總結(jié)》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對大家java程序設(shè)計有所幫助。

相關(guān)文章

  • Java中 URL實現(xiàn)斷點下載

    Java中 URL實現(xiàn)斷點下載

    Java中 URL實現(xiàn)斷點下載,需要的朋友可以參考一下
    2013-03-03
  • Java TCP編程之Scoket

    Java TCP編程之Scoket

    TCP/IP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,它會保證數(shù)據(jù)不丟包、不亂序。TCP全名是Transmission Control Protocol,它是位于網(wǎng)絡(luò)OSI模型中的第四層
    2022-11-11
  • Java實現(xiàn)兩人五子棋游戲(三) 畫出棋子

    Java實現(xiàn)兩人五子棋游戲(三) 畫出棋子

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)兩人五子棋游戲,畫出五子棋的棋子,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Java 使用 FFmpeg 處理視頻文件示例代碼詳解

    Java 使用 FFmpeg 處理視頻文件示例代碼詳解

    這篇文章主要介紹了Java 使用 FFmpeg 處理視頻文件示例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot實現(xiàn)多租戶架構(gòu)

    SpringBoot實現(xiàn)多租戶架構(gòu)

    在SpringBoot中可以通過多數(shù)據(jù)源和動態(tài)路由來實現(xiàn)多租戶機(jī)制,本文主要介紹了SpringBoot實現(xiàn)多租戶架構(gòu),具有一定的參考價值,感興趣的可以里哦啊接一下
    2024-03-03
  • Spring Cache和EhCache實現(xiàn)緩存管理方式

    Spring Cache和EhCache實現(xiàn)緩存管理方式

    這篇文章主要介紹了Spring Cache和EhCache實現(xiàn)緩存管理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java的MyBatis框架中對數(shù)據(jù)庫進(jìn)行動態(tài)SQL查詢的教程

    Java的MyBatis框架中對數(shù)據(jù)庫進(jìn)行動態(tài)SQL查詢的教程

    這篇文章主要介紹了Java的MyBatis框架中對數(shù)據(jù)庫進(jìn)行動態(tài)SQL查詢的教程,講解了MyBatis中一些控制查詢流程的常用語句,需要的朋友可以參考下
    2016-04-04
  • SparkSQL讀取hive數(shù)據(jù)本地idea運行的方法詳解

    SparkSQL讀取hive數(shù)據(jù)本地idea運行的方法詳解

    這篇文章主要介紹了SparkSQL讀取hive數(shù)據(jù)本地idea運行的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • 最新評論

    苗栗市| 墨脱县| 佛山市| 青铜峡市| 长泰县| 监利县| 平罗县| 长海县| 加查县| 德钦县| 建平县| 聊城市| 盖州市| 甘谷县| 衡阳县| 黑山县| 云安县| 营口市| 梓潼县| 耒阳市| 健康| 正安县| 伊金霍洛旗| 松阳县| 灵台县| 自治县| 佳木斯市| 若尔盖县| 泗阳县| 富宁县| 铜川市| 武夷山市| 福安市| 华坪县| 永济市| 静安区| 烟台市| 邛崃市| 黑龙江省| 铜山县| 株洲县|