Java是这个类线程安全的

时间:2014-02-27 13:30:26

标签: java android multithreading google-maps thread-safety

就我而言,我为 Google Maps v2 (Android)编写课程,以组织移动/缩放操作的队列。如果您知道在第一个动画仍在运行时另一个动画已启动,则取消动画操作。

为了避免这个问题我写了课。它工作但我想知道它是线程安全吗?也许我错过了什么?提前谢谢。

public class MapDecoratorQueue {

    private List<MapDecorator> queue = new Vector<MapDecorator>();
    private boolean isRunning = false;

    public synchronized void add(MapDecorator md) {
        if (isRunning) {
            queue.add(md);
        } else {
            queue.clear();
            queue.add(md);
            next(0);
            isRunning = true;
        }
    }

    private void next(final int pos) {
        if (queue.isEmpty()) {
            isRunning = false;
        } else {
            MapDecorator decorator = queue.get(pos);
            L.log(MapDecoratorQueue.class.getSimpleName(), "isMove: "
                    + decorator.isMove() + " isZoom: " + decorator.isZoom());
            if (decorator.isMove()) {
                decorator.map.moveCamera(decorator.move);
            }
            if (decorator.isZoom()) {
                decorator.map.animateCamera(decorator.zoom,
                        decorator.zoomDuration, new CancelableCallback() {

                            @Override
                            public void onFinish() {
                                queue.remove(pos);
                                next(pos);
                            }

                            @Override
                            public void onCancel() {
                                L.log(MapDecoratorQueue.class.getSimpleName(),
                                        "cancelled");
                                queue.clear();
                                isRunning = false;
                            }
                        });
            }
        }
    }

    public static class MapDecorator {
        private GoogleMap map = null;
        private CameraUpdate move = null;
        private CameraUpdate zoom = null;
        private int zoomDuration = 0;

        /**
         * Для передвижения камеры и анимации
         * 
         * @param move
         * @param zoom
         * @param zoomDuration
         */
        public MapDecorator(GoogleMap map, CameraUpdate move,
                CameraUpdate zoom, int zoomDuration) {
            this.map = map;
            this.move = move;
            this.zoom = zoom;
            this.zoomDuration = zoomDuration;
        }

        /**
         * Только для передвижения камеры
         * 
         * @param move
         */
        public MapDecorator(GoogleMap map, CameraUpdate move) {
            this(map, move, null, 0);
        }

        /**
         * Только для зума камеры
         * 
         * @param zoom
         * @param zoomDuration
         */
        public MapDecorator(GoogleMap map, CameraUpdate zoom, int zoomDuration) {
            this(map, null, zoom, zoomDuration);
        }

        public boolean isMove() {
            return map != null && move != null;
        }

        public boolean isZoom() {
            return map != null & zoom != null && zoomDuration >= 0;
        }

        public CameraUpdate getMove() {
            return move;
        }

        public CameraUpdate getZoom() {
            return zoom;
        }

        public int getZoomDuration() {
            return zoomDuration;
        }
    }

}

2 个答案:

答案 0 :(得分:1)

列表(cas中的Vector)是线程安全的,但是使用的运行方式不是。当线程尝试使用下一个方法获取元素时,当另一个尝试使用add添加一个元素时,您可以有一个竞争条件。如果第一个线程就在将isRunning设置为false之前,第二个线程在此时检查它就会出现问题。

将synchronized添加到next方法将解决问题。

答案 1 :(得分:1)

如果在下面的行中,可以异步使用CancelableCallback,那么当您将对下一个(pos)方法的访问权限泄露给其他线程时就会遇到麻烦,在这种情况下,MapDecoratorQueue不是ThreadSafe。

decorator.map.animateCamera(decorator.zoom,decorator.zoomDuration, new CancelableCallback(pos));

无论如何,根据Brian Goetz :),线程安全不应该依赖于客户端实现(在这种情况下是animatecamera)所以你的类不是线程安全的。为了使线程安全,你可以使下一步同步,如果你这样做,你不需要向量。 ArrayList可以正常工作。