1. 程式人生 > >Google guava 中的Monitor

Google guava 中的Monitor

synchronized

自從Java提供了多執行緒程式設計,我們經常需要處理這樣的情況:在特定的時間,我們需要限制訪問,確保只有一個執行緒訪問我們的程式碼。Java提供了同步關鍵字synchronized來實現這種訪問控制,但是使用synchronized會存在一些問題。第一個問題是,當我們需要呼叫執行緒的wait()方法時,我們必須記得去使用while迴圈。看下面例子,來自guava monitor api上的說明:

 public class SafeBox<V> {
    private V value;

    public synchronized V get() throws InterruptedException {
        while (value == null) {
            wait();
        }
        V result = value;
        value = null;
        notifyAll();
        return result;
    }

    public synchronized void set(V newValue) throws InterruptedException {
        while (value != null) {
            wait();
        }
        value = newValue;
        notifyAll();
    }
}

在這個例子中獲取一個值,當值不存在的時候,我們等待。。。有值的時候需要notifyAll()。這裡需要注意的是,我們要在while迴圈中使用wait方法,而不是if。另外用notifyAll而不是notify。

ReentrantLock

在java.util.concurrent包中提供了ReentrantLock,我們使用它來實現上面的場景看看

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

public class SafeBox<V> {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition valuePresent = lock.newCondition();
    private final Condition valueAbsent = lock.newCondition();
    private V value;

    public V get() throws InterruptedException {
        lock.lock();
        try {
            while (value == null) {
                valuePresent.await();
            }
            V result = value;
            value = null;
            valueAbsent.signal();
            return result;
        } finally {
            lock.unlock();
        }
    }

    public void set(V newValue) throws InterruptedException {
        lock.lock();
        try {
            while (value != null) {
                valueAbsent.await();
            }
            value = newValue;
            valuePresent.signal();
        } finally {
            lock.unlock();
        }
    }
} 

我們依然需要使用while迴圈,但是有一個好處,我們可以定義兩個Condition,這樣我們就可以用signal來替代signalAll,這樣可能會帶來一點效能上的提升。

Monitor

Monitor是一個支援任意布林條件的同步的抽象,Monitor類是作為ReentrantLock的一個替代,程式碼中使用Monitor比使用ReentrantLock更不易出錯,可讀性也更強,並且也沒有顯著的效能損失,使用Monitor甚至有潛在的效能得到優化,下面我們看看用guava中的Monitor怎麼重寫上面的程式碼

package com.hupengcool.guava.concurrency;

import com.google.common.util.concurrent.Monitor;

public class SafeBox<V> {
    private final Monitor monitor = new Monitor();
    private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) {
        public boolean isSatisfied() {
            return value != null;
        }
    };
    private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) {
        public boolean isSatisfied() {
            return value == null;
        }
    };
    private V value;

    public V get() throws InterruptedException {
        monitor.enterWhen(valuePresent);
        try {
            V result = value;
            value = null;
            return result;
        } finally {
            monitor.leave();
        }
    }

    public void set(V newValue) throws InterruptedException {
        monitor.enterWhen(valueAbsent);
        try {
            value = newValue;
        } finally {
            monitor.leave();
        }
    }
}

可以發現使用guava之後,我們不需要使用while,使用Monitor.Guard定義進入程式碼快的條件即可,程式碼變得更加容易閱讀,寫起來也更加方便。
當我們Monitor的方法返回boolean值的時候,我們在if塊中包含try-finally塊,確保鎖能夠釋放。

if(monitor.enterIf(guard)){
    try{
       ...work..
    }finally{
        monitor.leave();
    }
}else{
   .. monitor not available..
}

當monitor的方法不返回任何值的時候,我們的程式碼也需要在finally中釋放鎖

monitor.enter()
try{
    ...work..
}finally{
    monitor.leave();
}

Monitor有幾個常用的方法

  • enter():進入到當前Monitor,無限期阻塞,等待鎖。
  • enter(long time, TimeUnit unit):進入到當前Monitor,最多阻塞給定的時間,返回是否進入Monitor。
  • tryEnter():如果可以的話立即進入Monitor,不阻塞,返回是否進入Monitor。
  • enterWhen(Guard guard):進入當前Monitor,等待Guard的isSatisfied()為true後,繼續往下執行 ,但可能會被打斷。
  • enterIf(Guard guard):如果Guard的isSatisfied()為true,進入當前Monitor。等待獲得鎖,不需要等待Guard satisfied。
  • tryEnterIf(Guard guard):如果Guard的isSatisfied()為true並且可以的話立即進入Monitor,不等待獲取鎖,也不等待Guard satisfied。

相關推薦

Google guava Monitor

synchronized 自從Java提供了多執行緒程式設計,我們經常需要處理這樣的情況:在特定的時間,我們需要限制訪問,確保只有一個執行緒訪問我們的程式碼。Java提供了同步關鍵字synchronized來實現這種訪問控制,但是使用synchronized會存在一些問題。第一個問題是,當我們需要呼叫執行緒的

Google GuavaPreconditions的用法,讓前置條件判斷變得更優雅

這幾天看Fresco和Glide的程式碼,發現他們都使用了Preconditions來做前置判斷條件,發現這樣寫,程式碼變得既優雅又容易除錯。 Preconditions的用法 OK,先看看平常寫程式碼我們是怎麼做的引數判斷。 判斷引數,如果引數配置錯

[Google Guava] 2.3-強大的集合工具類:java.util.Collections未包含的集合工具

原文連結 譯文連結 譯者:沈義揚,校對:丁一 尚未完成: Queues, Tables工具類 任何對JDK集合框架有經驗的程式設計師都熟悉和喜歡java.util.Collections包含的工具方法。Guava沿著這些路線提供了更多的工具方法:適用於所有集合的靜態方法。這是Guava最流行和

[Google Guava]--java.util.Collections未包含的集合工具(com.google.common.collect)

任何對JDK集合框架有經驗的程式設計師都熟悉和喜歡java.util.Collections包含的工具方法。Guava沿著這些路線提供了更多的工具方法:適用於所有集合的靜態方法。這是Guava最流行和成熟的部分之一。我們用相對直觀的方式把工具類與特定集合介面的對應關係歸納如下

Google Guava集合在實體類的應用示例

將實體list,轉換成map,拿到所有id的集合方法。減少訪問資料庫。 實體基類BaseEntity package com.mytest; import org.apache.commons.lang3.builder.ToStringBuilder; import

GuavaTreeRangeMap基本使用

add static attr_ att keyword markdown sys hide fadein RangeMap跟一般的Map一樣。存儲鍵值對,依照鍵來取值。不同於Map的是鍵的類型必須是Range,也既是一個區間。RangeMap在Guav

C#Monitor和Lock以及區別

能夠 program tor 試圖 tro 指定 object span () 原文地址:http://www.cnblogs.com/chengxingliang/p/3150731.html   Monitor對象   1.Monitor.Enter(object)方法

Google Map的瓦片

編號 png 四叉樹 放大 leo 5.0 app 開始 公式 一、墨卡托投影google map使用的是EPSG:900913標準墨卡托投影(等角圓術地圖投影)y = R*ln(tan(pi/4 + a/2))x = R*b當y等於piR時,投影圖正好為一個正方形,可行

Google Guava 類庫簡介

math dir 多好 spa 裝飾 ava collect mon 集合接口   Guava 是一個 Google開發的 基於java的類庫集合的擴展項目,包括 collections, caching, primitives support, concurrency l

guava的SettableFuture分析

沒有 ext 分析 runnable 查詢 rac 兩個 理解 同步隊列 當緩存中沒有要找的數據時,則要從數據庫中去查詢,而當並發量比較大時可能會擊穿數據庫,所以guava cache對同一值的查詢做了合並請求的處理。其中就用到了SettableFuture,類似一把鎖,只

Google線程框架com.google.guava

oca con and HA 1.0 zhang mat ole tin pom.xml<dependency> <groupId>com.google.guava</groupId> <artifactId>

Guava針對集合的 filter和過濾功能

操作 rri 根據 lis name 說明 ase 不包含 all 在guava庫中,自帶了過濾器(filter)的功能,可以用來對collection 進行過濾,先看例子: import com.google.common.base.Predicates; impor

【轉載】使用 Google Guava 美化你的 Java 代碼

detail ons http osc details 轉載 .net common article 轉載地址: https://blog.csdn.net/wisgood/article/details/13297535 原文地址:https://my.oschina.n

[Google Guava] 1-4 排序: Guava強大的”流暢風格比較器”

判斷 cal java width reverse right col tor res 原文鏈接 譯者: 沈義揚 排序器[Ordering]是Guava流暢風格比較器[Comparator]的實現,它可以用來為構建復雜的比較器,以完成集合排序的功能。 從實現上說,Orde

[Google Guava] 1.3-常見Object方法

情況 false pareto except col 順序 javase acl http 原文鏈接 譯者: 沈義揚 equals 當一個對象中的字段可以為null時,實現Object.equals方法會很痛苦,因為不得不分別對它們進行null檢查。使用Objects.e

Google Guava Stopwatch(計時器)

  Stopwatch stopwatch =newStopwatch().start(); //do something test for(int i =0; i <10000; i++){   } long nanos = stopwatch.elapsed(TimeUnit.NA

google瀏覽器 檢視記住的賬號和密碼

  對於一個有“健忘症”的人來說,密碼形同虛設。。設定了就忘記,每次登陸都要重新設定密碼。。。       然後,無意中發現,谷歌瀏覽器點過一次記住密碼後,竟然可以明文檢視賬號和密碼!! 步驟: 1、開啟谷歌瀏覽器,在右上角的選單項中,選擇設定選項   2

Google Guava官方教程

原文連結 譯文連結 譯者: 沈義揚,羅立樹,何一昕,*武祖 * 校對:方騰飛 引言 Guava工程包含了若干被Google的 Java專案廣泛依賴 的核心庫,例如:集合 [collections] 、快取 [caching] 、原生型別支援 [primitives support] 、併發庫 [

guava的工具集合 五

工具集合 比較和介紹 每個使用過jdk collections 的工具集合都知道java.util.Collections中的方法。guava提供了更多的工具:所有集合都可以使用靜態的方法。這些是guava中很受歡迎的部分 在jdk7之前建立集合需要重複的引數操作   List&l

Google Guava

Google guava通了強大的工具類來簡化程式碼。列舉常用的集中類: 原文:https://ifeve.com/google-guava/ //不可變集合 ImmutableList<Integer> list = ImmutableList.