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

Java并發(fā)編程之對象的組合

 更新時(shí)間:2022年04月07日 14:50:30   作者:萬貓學(xué)社  
這篇文章主要介紹了Java并發(fā)編程之對象的組合,文章基于Java的相關(guān)資料展開主題內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

1. 設(shè)計(jì)線程安全的類

在設(shè)計(jì)線程安全類的過程中,需要包含以下三個(gè)基本要素:

  • 找出構(gòu)成對象狀態(tài)的所有變量。
  • 找出約束變量的不變性條件。
  • 建立對象狀態(tài)的并發(fā)訪問管理策略。

1.1 收集同步需求

在很多類中都定義了一些不可變條件,用于判斷狀態(tài)是否有效。比如:計(jì)數(shù)器的取值范圍上存在一個(gè)限制,就是不能是負(fù)值。在操作中還會包含一些后驗(yàn)條件來判斷狀態(tài)遷移是否有有效。比如:計(jì)數(shù)器的當(dāng)前狀態(tài)為8,那么下一個(gè)有效狀態(tài)只能是9。由于不變性條件和后驗(yàn)條件在狀態(tài)及狀態(tài)轉(zhuǎn)換上施加了各種約束,因此就需要額外的同步和封裝。

1.2 依賴狀態(tài)的操作

在某些對象的方法中還包含一些基于狀態(tài)的先驗(yàn)條件。比如:不能從空隊(duì)列中移除一個(gè)元素,在刪除元素前,隊(duì)列必須處于非空狀態(tài)。如果在某個(gè)操作中包含有基于狀態(tài)的先驗(yàn)條件,那么這個(gè)操作就稱為依賴狀態(tài)的操作。

1.3 狀態(tài)的所有權(quán)

對象封裝了它擁有的狀態(tài),那么它就擁有封裝狀態(tài)的所有權(quán)。狀態(tài)的所有者將決定采用何種加鎖協(xié)議來維持狀態(tài)的完整性。所有權(quán)意味著控制權(quán)。如果發(fā)布了某個(gè)可變對象的引用,那么就不再擁有獨(dú)占的控制權(quán),最多是共享控制權(quán)。為了防止多個(gè)線程在并發(fā)訪問同一個(gè)對象時(shí)產(chǎn)生相互干擾,這些對象應(yīng)該要么是線程安全的對象,要么是事實(shí)不可變的對象,或者用同一個(gè)鎖保護(hù)的對象。

2. 實(shí)例封閉

將數(shù)據(jù)封裝在對象內(nèi)部,可以將數(shù)據(jù)的訪問限制在對象的方法上,從而更容易確保線程在訪問數(shù)據(jù)是總能持有正確的鎖。被封閉對象一定不能超過它們既定的作用域。對象可以封閉在類的一個(gè)實(shí)例中,比如:作為類的一個(gè)私有成員;或者封閉在某個(gè)作用域內(nèi),比如:作為一個(gè)局部變量;或者封閉在線程中,比如:在某個(gè)線程中將對象從一個(gè)方法傳遞到另一個(gè)方法,而不是在多個(gè)線程之間共享該對象。

封閉機(jī)制更易于構(gòu)造線程安全的類,因?yàn)楫?dāng)封閉類的狀態(tài)時(shí),在分析類的線程安全性時(shí)就無須檢測整個(gè)程序。

2.1 Java監(jiān)視器模式

遵循Java監(jiān)視器模式的對象會把對象的所有可變狀態(tài)都封裝起來,并由對象自己的內(nèi)置鎖來保護(hù)。示例:一個(gè)用于調(diào)度車輛的“車輛跟蹤器”,每臺車都由一個(gè)String對象來標(biāo)識,并且擁有一個(gè)對應(yīng)的位置坐標(biāo)(x,y)。創(chuàng)建一個(gè)追蹤器類用來封裝所有車輛的標(biāo)識和位置,該類由多個(gè)線程(讀取操作和更新操作)共享。

@NotThreadSafe
public class MutablePoint {
    public int x, y;

    public MutablePoint() {
        x = 0;
        y = 0;
    }

    public MutablePoint(MutablePoint p) {
        this.x = p.x;
        this.y = p.y;
    }
}
@ThreadSafe
public class MonitorVehicleTracker {
    @GuardedBy("this") private final Map<String, MutablePoint> locations;

    public MonitorVehicleTracker(Map<String, MutablePoint> locations) {
        this.locations = deepCopy(locations);
    }

    public synchronized Map<String, MutablePoint> getLocations() {
        return deepCopy(locations);
    }

    public synchronized MutablePoint getLocation(String id) {
        MutablePoint loc = locations.get(id);
        return loc == null ? null : new MutablePoint(loc);
    }

    public synchronized void setLocation(String id, int x, int y) {
        MutablePoint loc = locations.get(id);
        if (loc == null)
            throw new IllegalArgumentException("No such ID: " + id);
        loc.x = x;
        loc.y = y;
    }

    private static Map<String, MutablePoint> deepCopy(Map<String, MutablePoint> m) {
        Map<String, MutablePoint> result = new HashMap<String, MutablePoint>();

        for (String id : m.keySet())
            result.put(id, new MutablePoint(m.get(id)));

        return Collections.unmodifiableMap(result);
    }
}

雖然類MutablePoint不是線程安全的,但是追蹤器類是線程安全的。它所包含的Map對象和可變的Point對象都未曾發(fā)布。當(dāng)需要回去車輛的位置時(shí),通過拷貝構(gòu)造函數(shù)或deepCopy方法復(fù)制正確的值,從而生成一個(gè)新的Map對象。車輛少是,這并不存在性能問,單在車輛數(shù)量非常大的情況下將極大地降低性能。

3. 線程安全性的委托

大多數(shù)對象都是組合對象。當(dāng)從頭開始構(gòu)建一個(gè)類,或者將多個(gè)非線程安全的類組合為一個(gè)類時(shí),Java監(jiān)視器模式是非常有用的。但是,如果類中的各個(gè)組件都已經(jīng)是線程安全的,那么實(shí)現(xiàn)線程安全就應(yīng)視情況而定。

3.1 基于委托的車輛追蹤器

保存車輛位置信息的Map類,使用線程安全的ConcurrentMap類代替。

使用不可變的Point類來代替MutablePoint類:

public class Point {
    public final int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

在DelegatingVehicleTracker中沒有使用顯式的同步,所有對狀態(tài)的訪問都由ConcurrentHashMap來管理:

@ThreadSafe
public class DelegatingVehicleTracker {
    private final ConcurrentMap<String, Point> locations;
    private final Map<String, Point> unmodifiableMap;

    public DelegatingVehicleTracker(Map<String, Point> points) {
        locations = new ConcurrentHashMap<String, Point>(points);
        unmodifiableMap = Collections.unmodifiableMap(locations);
    }

    public Map<String, Point> getLocations() {
        return unmodifiableMap;
    }

    public Point getLocation(String id) {
        return locations.get(id);
    }

    public void setLocation(String id, int x, int y) {
        if (locations.replace(id, new Point(x, y)) == null)
            throw new IllegalArgumentException("invalid vehicle name: " + id);
    }
}

在使用監(jiān)視器模式的車輛追蹤器中返回的是車輛位置的快照,而在使用委托的車輛追蹤器中返回的是一個(gè)不可修改卻實(shí)時(shí)的車輛位置信息。

3.2 獨(dú)立的狀態(tài)變量

我們還可以將線程安全性委托給多個(gè)狀態(tài)變量,只要這些變量是彼此獨(dú)立的,即組合而成的類并不會在其包含的多個(gè)狀態(tài)變量上增加任何不變形條件。

public class VisualComponent {
    private final List<KeyListener> keyListeners
            = new CopyOnWriteArrayList<KeyListener>();
    private final List<MouseListener> mouseListeners
            = new CopyOnWriteArrayList<MouseListener>();

    public void addKeyListener(KeyListener listener) {
        keyListeners.add(listener);
    }

    public void addMouseListener(MouseListener listener) {
        mouseListeners.add(listener);
    }

    public void removeKeyListener(KeyListener listener) {
        keyListeners.remove(listener);
    }

    public void removeMouseListener(MouseListener listener) {
        mouseListeners.remove(listener);
    }
}

VisualComponent類是一個(gè)圖形組件,允許客戶程序注冊監(jiān)控鼠標(biāo)和鍵盤等事件的監(jiān)聽器。在鼠標(biāo)事件監(jiān)聽器和鍵盤事件監(jiān)聽器之間不存在任何關(guān)聯(lián),二者是彼此獨(dú)立的,因此VisualComponent可以將其線程安全性委托給這兩個(gè)線程安全的監(jiān)聽器列表。

如果一個(gè)類是由多個(gè)獨(dú)立且線程安全的狀態(tài)變量組成,并且在所有的操作中都不包含無效狀態(tài)轉(zhuǎn)換,那么可以將線程安全性委托給底層的狀態(tài)變量。

3.3 發(fā)布底層的狀態(tài)變量

如果一個(gè)狀態(tài)變量是線程安全的,并且沒有任何不變性條件來約束它的值,在變量的操作上也不存在任何不允許的狀態(tài)轉(zhuǎn)換,那么就可以安全地發(fā)布這個(gè)變量。我們來修改之前的車輛追蹤器的代碼,使其發(fā)布底層的可變狀態(tài)。

首先寫一個(gè)可變并且線程安全的Point類:

public class SafePoint {
    @GuardedBy("this") private int x, y;

    private SafePoint(int[] a) {
        this(a[0], a[1]);
    }

    public SafePoint(SafePoint p) {
        this(p.get());
    }

    public SafePoint(int x, int y) {
        this.set(x, y);
    }

    public synchronized int[] get() {
        return new int[]{x, y};
    }

    public synchronized void set(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

再修改追蹤器的代碼:

public class PublishingVehicleTracker {
    private final Map<String, SafePoint> locations;
    private final Map<String, SafePoint> unmodifiableMap;

    public PublishingVehicleTracker(Map<String, SafePoint> locations) {
        this.locations = new ConcurrentHashMap<String, SafePoint>(locations);
        this.unmodifiableMap = Collections.unmodifiableMap(this.locations);
    }

    public Map<String, SafePoint> getLocations() {
        return unmodifiableMap;
    }

    public SafePoint getLocation(String id) {
        return locations.get(id);
    }

    public void setLocation(String id, int x, int y) {
        if (!locations.containsKey(id))
            throw new IllegalArgumentException("invalid vehicle name: " + id);
        locations.get(id).set(x, y);
    }
}

PublishingVehicleTracker中,其線程安全性委托給底層的ConcurrentHashMap,只是Map中的元素是線程安全的可變的。getLocations方法返回底層Map對象的一個(gè)不可變副本,調(diào)用者不能增加或刪除車輛,但可以通過修改返回Map中的SafePoint值來修改車輛的問題。

到此這篇關(guān)于Java并發(fā)編程之對象的組合的文章就介紹到這了,更多相關(guān)Java對象的組合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot2.x整合redis知識點(diǎn)講解

    springboot2.x整合redis知識點(diǎn)講解

    在本篇文章中小編給大家分享的是一篇關(guān)于springboot2.x整合redis知識點(diǎn)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2020-01-01
  • java 橋模式(Bridge Pattern)詳解

    java 橋模式(Bridge Pattern)詳解

    這篇文章主要介紹了java 橋模式(Bridge Pattern)詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 詳解Mybatis極其(最)簡(好)單(用)的一個(gè)分頁插件

    詳解Mybatis極其(最)簡(好)單(用)的一個(gè)分頁插件

    這篇文章主要介紹了詳解Mybatis極其(最)簡(好)單(用)的一個(gè)分頁插件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-12-12
  • java 替換docx文件中的字符串方法實(shí)現(xiàn)

    java 替換docx文件中的字符串方法實(shí)現(xiàn)

    這篇文章主要介紹了java 替換docx文件中的字符串方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Springboot使用切面功能詳解

    Springboot使用切面功能詳解

    Spring?Boot?是一個(gè)基于Spring框架的項(xiàng)目,它簡化了基于Spring的應(yīng)用開發(fā),這篇文章主要介紹了?Spring?Boot?中的切面功能,需要的可以了解下
    2025-01-01
  • Java中八大包裝類舉例詳解(通俗易懂)

    Java中八大包裝類舉例詳解(通俗易懂)

    這篇文章主要介紹了Java中的包裝類,包括它們的作用、特點(diǎn)、用途以及如何進(jìn)行裝箱和拆箱,包裝類還提供了許多實(shí)用方法,如轉(zhuǎn)換、獲取基本類型值、比較和類型檢測,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • 解決java.net.SocketTimeoutException: Read timed out的問題

    解決java.net.SocketTimeoutException: Read timed out的問題

    這篇文章主要介紹了解決java.net.SocketTimeoutException: Read timed out的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java中forEach使用lambda表達(dá)式,數(shù)組和集合的區(qū)別說明

    Java中forEach使用lambda表達(dá)式,數(shù)組和集合的區(qū)別說明

    這篇文章主要介紹了Java中forEach使用lambda表達(dá)式,數(shù)組和集合的區(qū)別說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中BeanUtils.copyProperties的11個(gè)坑總結(jié)

    Java中BeanUtils.copyProperties的11個(gè)坑總結(jié)

    我們?nèi)粘i_發(fā)中,經(jīng)常涉及到DO、DTO、VO對象屬性拷貝賦值,很容易想到org.springframework.beans.BeanUtils的copyProperties,它會自動通過反射機(jī)制獲取源對象和目標(biāo)對象的屬性,pyProperties,會有好幾個(gè)坑呢,本文將給大家總結(jié)一下遇到的坑,需要的朋友可以參考下
    2023-05-05
  • Java基礎(chǔ)之匿名內(nèi)部類、包裝類

    Java基礎(chǔ)之匿名內(nèi)部類、包裝類

    這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08

最新評論

贞丰县| 曲靖市| 海盐县| 德惠市| 阿坝| 黔东| 南城县| 临澧县| 鹤峰县| 富蕴县| 宁陕县| 繁峙县| 龙州县| 云林县| 利辛县| 沙坪坝区| 建始县| 贵德县| 井陉县| 准格尔旗| 和林格尔县| 泰顺县| 永城市| 龙泉市| 浙江省| 陇西县| 临桂县| 日照市| 彭阳县| 阳西县| 台南县| 乌拉特后旗| 宜兰县| 京山县| 通江县| 平凉市| 黔南| 通道| 阿瓦提县| 锡林郭勒盟| 琼结县|