-1

我正在尝试实现锁,我不希望在我写的时候发生读取。

以下是我ClientData正在使用的课程CountDownLatch-

public class ClientData {

    private static final AtomicReference<Map<String, Map<Integer, String>>> primaryMapping = new AtomicReference<>();
    private static final AtomicReference<Map<String, Map<Integer, String>>> secondaryMapping = new AtomicReference<>();
    private static final AtomicReference<Map<String, Map<Integer, String>>> tertiaryMapping = new AtomicReference<>();

    // should this be initialized as 1?
    private static final CountDownLatch hasBeenInitialized = new CountDownLatch(1) 

    public static Map<String, Map<Integer, String>> getPrimaryMapping() {
        try {
            hasBeenInitialized.await();
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }

        return primaryMapping.get();
    }

    public static void setPrimaryMapping(Map<String, Map<Integer, String>> map) {
        primaryMapping.set(map);
        hasBeenInitialized.countDown();
    }

    public static Map<String, Map<Integer, String>> getSecondaryMapping() {
        try {
            hasBeenInitialized.await();
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }

        return secondaryMapping.get();
    }       

    public static void setSecondaryMapping(Map<String, Map<Integer, String>> map) {
        secondaryMapping.set(map);
        hasBeenInitialized.countDown();
    }

    public static Map<String, Map<Integer, String>> getTertiaryMapping() {
        try {
            hasBeenInitialized.await();
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }

        return tertiaryMapping.get();
    }       

    public static void setTertiaryMapping(Map<String, Map<Integer, String>> map) {
        tertiaryMapping.set(map);
        hasBeenInitialized.countDown();
    }       
}

问题陈述:-

我需要等待上面代码中的get三个电话。AtomicReferences一旦对我的三个调用完成了所有写入AtomicReferencesset那么我将允许对我拥有的三个 getter 进行调用。

所以我决定使用CountDownLatch我初始化为的1?我需要初始化它3吗?每次在我进行新更新的第一组之前,我是否需要将倒计时闩锁重新设置回 3?因为我将AtomicReferences在单独的三个语句中设置这三个。

我猜我上面的代码有问题吗?

笔记:-

我将在其他班级进行这样的设置-

ClientData.setPrimaryMapping(primaryTables);
ClientData.setSecondaryMapping(secondaryTables);
ClientData.setTertiaryMapping(tertiaryTables);

其他一些线程在设置后必须从中读取数据AtomicReferences

更新:-

下面是我的后台线程代码,它将从 URL 获取数据,对其进行解析并将其存储在ClientData类变量中。

public class TempScheduler {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        public void startScheduler() {
            final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(new Runnable() {
                public void run() {
                try {
                    callServers();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                }
            }, 0, 10, TimeUnit.MINUTES);
        }
    }

    // call the servers and get the data and then parse 
    // the response.
    private void callServers() {
        String url = "url";
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);
        parseResponse(response);

    }

    // parse the response and store it in a variable
    private void parseResponse(String response) {
        //...       
        ConcurrentHashMap<String, Map<Integer, String>> primaryTables = null;
        ConcurrentHashMap<String, Map<Integer, String>> secondaryTables = null;
        ConcurrentHashMap<String, Map<Integer, String>> tertiaryTables = null;

        //...

        // store the data in ClientData class variables which can be
        // used by other threads
    ClientData.setPrimaryMapping(primaryTables);
    ClientData.setSecondaryMapping(secondaryTables);
    ClientData.setTertiaryMapping(tertiaryTables);
    }
}
4

2 回答 2

0

如果您想独立处理所有 3 个变量(即获得第三个变量不需要等待设置主要变量),这就是我阅读您的问题的方式,您只需为每个地图创建 1 个倒计时锁存器。每个设置器对正在设置的变量的相应锁存器进行倒计时。每个 getter 在各自的锁存器上调用 await。

于 2014-04-28T19:30:26.950 回答
0

此设置完全是过度杀伤 IMO。

这是一个可以正常工作并且更简单的替代方法:

public class MappingContainer {
     private final Map<String, Map<Integer, String>> primaryMapping;
     private final Map<String, Map<Integer, String>> secondaryMapping;
     private final Map<String, Map<Integer, String>> tertiaryMapping;

     // + constructor and getters
}

public class ClientData {
    private static volatile MappingContainer mappingContainer;

    // regular setters and getters
}

public class TempScheduler {
//...
    private void parseResponse(String response) {
        //...       
        ConcurrentHashMap<String, Map<Integer, String>> primaryTables = null;
        ConcurrentHashMap<String, Map<Integer, String>> secondaryTables = null;
        ConcurrentHashMap<String, Map<Integer, String>> tertiaryTables = null;

        //...

        // store the data in ClientData class variables which can be
        // used by other threads
        ClientData.setMappingContainer( new MappingContainer( primaryTables, secondaryTables, tertiaryTables );
    }
}

当更简单的构造不能削减它时,应该留给锁存器和原子引用。特别是,如果您必须对任何 N 个事件(而不是 3 个特定事件)进行计数,则锁存器非常有用,而原子引用仅在您使用 compare-and-set 或 get-and-set 习惯用法时才有用。

于 2014-04-28T19:48:06.040 回答