来自不同计划作业的同一列版本

时间:2019-01-12 03:23:15

标签: java sql json quartz-scheduler iot

我在table > column上存储了一个JSON对象。该JSON对象的示例是:

{
  a :{
    data: [1, 2, 3]
  },
  b :{
    data: [4, 5, 6]
  }
}

我有调度程序,用于在a.data (named scheduler A)b.data (named scheduler B)上附加值。调度程序正在一种从table > column获取JSON值并附加内容的方式。

问题:

此处scheduler Ascheduler B没有任何同步机制。因此,当scheduler Ascheduler B附加值事件同时发生时,scheduler A的输出将被scheduler B的输出覆盖,反之亦然。

处理同步的机制是什么?由于JSON值的行为将是动态的,因此我也无法在列上拆分JSON对象,因此必须使用该JSON格式。

1 个答案:

答案 0 :(得分:1)

在最简单的情况下,您可以同步数据库访问(例如,有一个用于读取/写入数据库的专用对象,可以在调度程序中使用此对象来访问/修改json数据,并在调度程序中对此对象进行同步)。

类似这样的东西:

MockDB类

public class MockDB {

    private JSONObject json;

    public MockDB() {
        this.json = fillJSON();
    }

    // fill JSON object with test data
    private JSONObject fillJSON() {
        JSONObject json = new JSONObject();

        JSONObject map = new JSONObject();
        map.put("data", Arrays.asList(1));
        json.put("a", map);

        map = new JSONObject();
        map.put("data", Arrays.asList(11));
        json.put("b", map);

        return json;
    }

    public JSONObject getJSON() {
        return cloneJson(json);
    }

    public void setJSON(JSONObject newJson) {
        this.json = cloneJson(newJson);
    }

    // make a deep copy of JSON object
    private JSONObject cloneJson(JSONObject jsonObj) {
        JSONObject newJson = new JSONObject();
        for(Object key : jsonObj.keySet()) {
            if (jsonObj.get(key) instanceof JSONObject) {
                newJson.put(key, cloneJson((JSONObject) jsonObj.get(key)));
            } else if (jsonObj.get(key) instanceof JSONArray) {
                newJson.put(key, ((JSONArray)jsonObj.get(key)).clone());
            } else {
                newJson.put(key, jsonObj.get(key));
            }
        }
        return newJson;
    }
}

字段更新程序类

public class ScheduledUpdater implements Runnable {

    private final MockDB database;
    private final String field;

    public ScheduledUpdater(MockDB database, String field) {
        this.database = database;
        this.field = field;
    }

    @Override
    public void run() {
        // here we should synchronize on a whole DB access object 
        // as we need get & set to be atomic together
        JSONObject json;
        synchronized (database) {
            json = database.getJSON();

            JSONObject xData;
            xData = (JSONObject) json.get(field);
            Object obj = xData.get("data");
            List<Integer> array = new ArrayList<>((List<Integer>) obj);
            array.add(Collections.max(array) + 1); // add new item to json array
            xData.put("data", array);

            database.setJSON(json);
        }
        printValues(json);
    }

    private void printValues(JSONObject json) {
        JSONObject    ao = (JSONObject) json.get("a");
        List<Integer> ad = (List<Integer>) ao.get("data");
        JSONObject    bo = (JSONObject) json.get("b");
        List<Integer> bd = (List<Integer>) bo.get("data");
        System.out.println(String.format("a: %02d; b: %02d", Collections.max(ad), Collections.max(bd)));
    }

}

实际执行人

    public static void main(String [] args) throws InterruptedException {

        MockDB database = new MockDB();

        System.out.println("starting tasks\n");

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        executor.scheduleAtFixedRate(new ScheduledUpdater(database, "a"), 0, 1, TimeUnit.SECONDS);
        executor.scheduleAtFixedRate(new ScheduledUpdater(database, "b"), 0, 1, TimeUnit.SECONDS);

        // run test for 5 seconds
        executor.awaitTermination(5, TimeUnit.SECONDS);
        executor.shutdown();

        // let all threads to stop
        Thread.sleep(250);
        System.out.println("\ntasks stopped; json: " + database.getJSON());
    }

PS:此外,您还可以从java.util.concurrent包中检查同步原语。