国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

《Java Concurrency in Practice》中三個(gè)VehicleTracker例子的

binaryTree / 715人閱讀

摘要:線(xiàn)程安全需求分析三個(gè)例子都是關(guān)于車(chē)輛追蹤的。他們使用了不同的方式來(lái)保證車(chē)輛追蹤類(lèi)的線(xiàn)程安全性。值得注意的值文檔也是維護(hù)線(xiàn)程安全的重要組成部分。

每個(gè)例子后面有代碼,大家可以先把代碼粘出來(lái)或者開(kāi)兩個(gè)頁(yè)面,先過(guò)一下例子的代碼,然后一邊看分析一遍看代碼,上下拖動(dòng)看的話(huà)效果不好。

歡迎拍磚和補(bǔ)充。

線(xiàn)程安全需求分析

三個(gè)例子都是關(guān)于車(chē)輛追蹤的。他們使用了不同的方式來(lái)保證車(chē)輛追蹤類(lèi)的線(xiàn)程安全性。
我們知道,如果要寫(xiě)一個(gè)線(xiàn)程安全類(lèi),那么首先得明確這個(gè)類(lèi)關(guān)于線(xiàn)程安全的需求。
那么這個(gè)類(lèi)的線(xiàn)程安全需求就是:
訪(fǎng)問(wèn)線(xiàn)程要么能夠看到寫(xiě)線(xiàn)程對(duì)location的x,y坐標(biāo)完整的寫(xiě)入,要么看不到。不允許出現(xiàn)訪(fǎng)問(wèn)線(xiàn)程只看到寫(xiě)線(xiàn)程寫(xiě)了其中一個(gè)坐標(biāo)。

比如線(xiàn)程A在訪(fǎng)問(wèn)location時(shí),只看到了B線(xiàn)程對(duì)location的x或者y坐標(biāo)的寫(xiě)入,那就破壞了這個(gè)類(lèi)的線(xiàn)程安全性。

例子1(MonitorVehicleTracker ) 對(duì) 線(xiàn)程不安全+可變 對(duì)象進(jìn)行實(shí)例封閉和加鎖

作者使用了實(shí)例封閉+加鎖機(jī)制保證了MonitorVehicleTracker類(lèi)的安全性。
實(shí)例封閉的意思就是將狀態(tài)的訪(fǎng)問(wèn)路徑限制在對(duì)象內(nèi)部,
實(shí)例限制后,只要對(duì)這些狀態(tài)的訪(fǎng)問(wèn)自始至終使用同一個(gè)鎖,就能保證其線(xiàn)程安全性。

MonitorVehicleTracker的唯一狀態(tài):locations,是一個(gè)HashMap對(duì)象,大家都知道它是可變的,也是線(xiàn)程不安全的。

構(gòu)造函數(shù)和getLocations都做了一次deepCopy。這兩個(gè)deepCopy都是必須的。deepCopy保證了將locations對(duì)象封裝在了MonitorVehicleTracker實(shí)例中,向外發(fā)布的只是一個(gè)拷貝的副本。想要訪(fǎng)問(wèn)locations這個(gè)狀態(tài),只能通過(guò)MonitorVehicleTracker對(duì)象,而所有的訪(fǎng)問(wèn)路徑,都加上了鎖。

deepCopy方法

返回結(jié)果使用了Collections.unmodifiableMap(map):這里不使用UnmodifiableMap,而是只是用deepCopy的HashMap也是可以的,但是文檔一定寫(xiě)清楚,返回的是deepCopy的Map。不然站在調(diào)用者的角度,如果對(duì)其進(jìn)行寫(xiě)操作,就不能獲得期望的結(jié)果。

值得注意的值 文檔也是維護(hù)線(xiàn)程安全的重要組成部分
就好比SynchronizedCollection的子類(lèi),這些同步容器在調(diào)用iterator方法時(shí)并沒(méi)有加鎖。
導(dǎo)致如果用戶(hù)需要讀寫(xiě)一致,那么在迭代的時(shí)候必須加鎖,而且這個(gè)鎖必須是創(chuàng)建的SynchronizedXXX對(duì)象本身。
如果對(duì)讀寫(xiě)一致沒(méi)那么敏感,那迭代的時(shí)候只需要處理一下ConcurrentModificationException即可。
這些都是在SynchronizedXXX文檔上寫(xiě)的很清楚的。

由于MutablePoint是可變的,如果deepCopy在迭代時(shí)不對(duì)每一個(gè)location進(jìn)行復(fù)制map.put(k, new MutablePoint(v.x,v.y));而是使用map.put(k, v);那getLocations發(fā)布出去的所有l(wèi)ocation就存在線(xiàn)程安全風(fēng)險(xiǎn),因?yàn)樵谕獠科渌€(xiàn)程得到location之后有可能對(duì)其進(jìn)行更新。getLocation是同樣的道理,發(fā)布出去的MutablePoint一定是副本。

locations字段的final是不是必須的?

我認(rèn)為不是,因?yàn)檫@里并不是希望把MonitorVehicleTracker變成不可變對(duì)象。
如果沒(méi)有final,那就必須注意,要使用安全的方式來(lái)發(fā)布MonitorVehicleTracker對(duì)象。

安全發(fā)布參見(jiàn)原書(shū)3.5節(jié)或者這個(gè)例子https://segmentfault.com/q/10...)

代碼
public class MonitorVehicleTracker {

    private final Map locations;

    public MonitorVehicleTracker(Map locations) {
        this.locations = deepCopy(locations);
    }

    public synchronized Map getLocations() {
        return deepCopy(locations);
    }

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

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


    private Map deepCopy(Map locations) {
        Map map = new HashMap<>();
        locations.forEach((k, v) -> {
            map.put(k, new MutablePoint(v.x, v.y));
        });
        return Collections.unmodifiableMap(map);
    }
}

/**
 * 可變,線(xiàn)程不安全
 */
class MutablePoint {
    public int x, y;

    public MutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
例子2(DelegatingVehicleTracker)

此類(lèi)對(duì)訪(fǎng)問(wèn)locations的所有方法都沒(méi)有加鎖,而是通過(guò)使用線(xiàn)程安全的ConcurrentHashMap來(lái)保證DelegatingVehicleTracker的線(xiàn)程安全性。相當(dāng)于是把線(xiàn)程安全行委托給了ConcurrentHashMap。

getLocations使用了UnmodifiableMap作為視圖返回。如果不使用UnmodifiableMap而是直接返回locations行不行?
我認(rèn)為是可以的,畢竟locations是ConcurrentHashMap類(lèi)型,它是線(xiàn)程安全的,并且作為DelegatingVehicleTracker的一個(gè)狀態(tài),并沒(méi)有什么約束條件,或者不允許有的狀態(tài)遷移操作。

這里使用UnmodifiableMap只是增強(qiáng)了封裝性,意味著,你想修改車(chē)輛位置,那必須通過(guò)DelegatingVehicleTracker對(duì)象上的方法來(lái)操作。

作者還提到另一種方法:下邊代碼中的getCopyedLocations方法。
這個(gè)方法和getLocations方法的區(qū)別是前者在不能夠?qū)崟r(shí)地反應(yīng)車(chē)輛位置的變化,而后者可以。

因?yàn)?b>Collections.unmodifiableMap(new HashMap<>(locations));在new HashMap時(shí)做了putAll.它將locations的所有元素淺復(fù)制了一份。所以當(dāng)locations有寫(xiě)入操作時(shí),HashMap并不能得知。

Collections.unmodifiableMap(locations)是將locations的引用保存在了UnmodifiableMap中,
所以當(dāng)locations有寫(xiě)入操作時(shí),UnmodifiableMap可以立即看到。

代碼
public class DelegatingVehicleTracker {

    private final ConcurrentHashMap locations;
    private final Map locationsView;

    public DelegatingVehicleTracker(Map points) {
        this.locations = new ConcurrentHashMap<>(points);
        this.locationsView = Collections.unmodifiableMap(this.locations);
    }

    public Map getLocations() {
        return locationsView;
    }

    public Map getCopyedLocations() {
        return Collections.unmodifiableMap(new HashMap<>(locations));
    }

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

    public void setLocation(String id, int x, int y) {
        if (locations.replace(id, new ImmutablePoint(x, y)) == null) {
            throw new IllegalArgumentException("No such id:" + id);
        }
    }
}

class ImmutablePoint {
    private final int x, y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
例子3(PublishVehicleTracker)

此類(lèi)和DelegatingVehicleTracker的區(qū)別:

使用了線(xiàn)程安全的SafePoint。

setLocation方法不再replace一個(gè)新構(gòu)造的ImmutablePoint。
因?yàn)镾afePoint和ConcurrentHashMap都是線(xiàn)程安全的,

所以這幾個(gè)方法都不需要額外的同步,或者復(fù)制,直接調(diào)用他們的修改狀態(tài)的方法是沒(méi)問(wèn)題的。

代碼
public class PublishVehicleTracker {

    private final ConcurrentHashMap locations;
    private final Map locationsView;

    public PublishVehicleTracker(Map points) {
        this.locations = new ConcurrentHashMap<>(points);
        this.locationsView = Collections.unmodifiableMap(this.locations);
    }

    public Map getLocations() {
        return locationsView;
    }

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

    public void setLocation(String id, int x, int y) {
        if (!locations.contains(id)) {
            throw new IllegalArgumentException("No such id:" + id);
        }
        locations.get(id).setXY(x, y);
    }
}

class SafePoint {
    private int x, y;

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

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

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

}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67854.html

相關(guān)文章

  • 學(xué)習(xí)Java必讀10本書(shū)籍

    摘要:學(xué)習(xí)編程的本最佳書(shū)籍這些書(shū)涵蓋了各個(gè)領(lǐng)域,包括核心基礎(chǔ)知識(shí),集合框架,多線(xiàn)程和并發(fā),內(nèi)部和性能調(diào)優(yōu),設(shè)計(jì)模式等。擅長(zhǎng)解釋錯(cuò)誤及錯(cuò)誤的原因以及如何解決簡(jiǎn)而言之,這是學(xué)習(xí)中并發(fā)和多線(xiàn)程的最佳書(shū)籍之一。 showImg(https://segmentfault.com/img/remote/1460000018913016); 來(lái)源 | 愿碼(ChainDesk.CN)內(nèi)容編輯 愿碼Slo...

    masturbator 評(píng)論0 收藏0
  • Treiber Stack簡(jiǎn)單分析

    摘要:在添加新項(xiàng)目時(shí)使用堆棧,將堆棧的頂部放在新項(xiàng)目之后。當(dāng)從堆棧中彈出一個(gè)項(xiàng)目時(shí),在返回項(xiàng)目之前,您必須檢查另一個(gè)線(xiàn)程自操作開(kāi)始以來(lái)沒(méi)有添加其他項(xiàng)目。比較和交換將堆棧的頭部設(shè)置為堆棧中舊的第二個(gè)元素,混合完整的數(shù)據(jù)結(jié)構(gòu)。 Abstract Treiber Stack Algorithm是一個(gè)可擴(kuò)展的無(wú)鎖棧,利用細(xì)粒度的并發(fā)原語(yǔ)CAS來(lái)實(shí)現(xiàn)的,Treiber Stack在 R. Kent T...

    junfeng777 評(píng)論0 收藏0
  • 深入理解Java內(nèi)存模型(六)——final

    摘要:對(duì)于域,編譯器和處理器要遵守兩個(gè)重排序規(guī)則在構(gòu)造函數(shù)內(nèi)對(duì)一個(gè)域的寫(xiě)入,與隨后把這個(gè)被構(gòu)造對(duì)象的引用賦值給一個(gè)引用變量,這兩個(gè)操作之間不能重排序。這個(gè)屏障禁止處理器把域的寫(xiě)重排序到構(gòu)造函數(shù)之外。下一篇深入理解內(nèi)存模型七總結(jié) 與前面介紹的鎖和volatile相比較,對(duì)final域的讀和寫(xiě)更像是普通的變量訪(fǎng)問(wèn)。對(duì)于final域,編譯器和處理器要遵守兩個(gè)重排序規(guī)則: 在構(gòu)造函數(shù)內(nèi)對(duì)一個(gè)fi...

    lixiang 評(píng)論0 收藏0
  • Java 8 并發(fā): Threads 和 Executors

    摘要:能夠異步的執(zhí)行任務(wù),并且通常管理一個(gè)線(xiàn)程池。這樣我們就不用手動(dòng)的去創(chuàng)建線(xiàn)程了,線(xiàn)程池中的所有線(xiàn)程都將被重用。在之后不能再提交任務(wù)到線(xiàn)程池。它不使用固定大小的線(xiàn)程池,默認(rèn)情況下是主機(jī)的可用內(nèi)核數(shù)。 原文地址: Java 8 Concurrency Tutorial: Threads and Executors Java 5 初次引入了Concurrency API,并在隨后的發(fā)布版本中...

    J4ck_Chan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<