1_基础知识_chapter04_对象的组合_3_线程安全性的委

2019-01-21  本文已影响0人  米都都
__2° 基于委托的车辆追踪__

DelegatingVehicleTracker.java

    @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 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);
            }
        }

        public Map<String, Point> getLocations() {

            return unmodifiableMap;
        }

        // Alternate version of getLocations 
        public Map<String, Point> getLocationsAsStatic() {
    
            return Collections.unmodifiableMap(new HashMap<String, Point>(locations));
        }
    }

Point.java

    @Immutable
    public class Point {

        public final int x, y;

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

这种方式将线程安全委托给了ConcurrentMap类型的locations, 由于Point类时不可变的,所以如果想要实时更新点的位置, 可以调用getLocations()函数, 这样更新会立刻显示; 如果不需要发生变化的车辆位置, 可以调用getLocationsAsStatic()函数, 在这里采用了__浅拷贝__的方式(因为Point不可变, 复制Map的结构即可, 不需要复制它的内容)

(3) __线程安全性可以委托给多个状态变量, 只要它们是彼此独立的__

示例

    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);
        }
    }

这个示例中, keyListeners和mouseListeners的类型是CopyOnWriteArrayList, 这是一个线程安全的容器类型, 并且由于它们互相独立, 所以VisualComponent的线程安全委托给了keyListeners和mouseListeners

(4) __但是, 如果某个类含有复合操作, 那么委托方式就会失效, 此时必须依靠类自己的加锁机制__(这个类似于如果只有一个状态变量时用volatile就行,但是有多个变量仅用volatile就会失效)
上一篇 下一篇

猜你喜欢

热点阅读