在多线程代码中的两个表中存储相同的ID

时间:2013-02-10 22:30:31

标签: java database multithreading concurrency atomicity

我已经开始研究一个项目,在这个项目中,我有两个表在不同的数据库中使用不同的模式。所以我将有两个不同的连接参数来连接数据库。在连接到每个数据库之后,我需要使用相应表中给出的sql插入这两个表。

我应该根据命令行参数插入所有两个表或其中任何一个使用JDBC。这意味着单个线程将插入Table1和Table2或其中任何一个。

命令行参数: - 这里10是线程数,100是任务数,table1和table2是表名。

10 100 table1 table2

以下是我的代码。在这段代码中会发生什么 - 假设我们只传递一个名为table1的表,那么它将通过使用用于table1的SQL插入到该表中。

此外,我还需要在idtable1中插入相同的table2idAtomicInteger作为Task传递给构造函数{{1} }。这意味着如果id is 1,则1 idtable1中的table2都应该存在。

 final AtomicInteger id = new AtomicInteger(1);

 ExecutorService service = Executors. newFixedThreadPool(noOfThreads);

 for (int i = 0; i < noOfTasks * noOfThreads; i++) {

      for (String arg : tableNames) {
          String url = (String) prop.get(arg + ".url");
          String user = (String) prop.get(arg + ".user");
          String password = (String) prop.get(arg + ".password");
          String driver = (String) prop.get(arg + ".driver");
          String suffix = (String) prop.get(arg + ".suffix");
          String sql = (String) prop.get(arg + ".sql");

          service.submit( new Task(id, url, user, password, driver, sql, suffix));
        }
    }

下面是实现Runnable接口的Task类

class Task implements Runnable {

    private final AtomicInteger id ;
    private final String url ;
    private final String username ;
    private final String password ;
    private final String sql ;
    private final String driver ;
    private final String suffix ;

    public Task(AtomicInteger id, String url, String user, String password, String driver, String sql, String suffix) {
        this.id = id;
        this.url = url;
        this.username = user;
        this.password = password;
        this.driver = driver;
        this.sql = sql;
        this.suffix = suffix;
    }

    @Override
    public void run() {

        try {

           dbConnection = getDBConnection(url , username , password , driver );
           callableStatement = dbConnection .prepareCall(sql);

           int userId = id .getAndIncrement();

           callableStatement.setString(1, String.valueOf(userId));

        //other callableStatement


        callableStatement.executeUpdate();
       }
    }

因此,如果我选择10,如果我运行上述程序,其中多个线程如线程数为1000,任务数为id1

然后在两个表中,相同的ID不存在,这意味着id 1将只存在于table1table2的一个表中。我能想到的唯一原因是idAtomicInteger所以每次为每个线程获得一个新的id。有什么办法可以在每个表中使用相同的id插入吗?然后确保id为PrimaryKey,这样如果每个线程再次插入这些表中,它们将获得一个新的id。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您应该将计数器定义为静态,以避免重复PrimaryKey

static AtomicInteger id;

然后将增量代码移动到主循环中(不要忘记删除int userId = id .getAndIncrement();类中的Task):

for (int i = 0; i < noOfTasks * noOfThreads; i++) {
  // add following line
  int userId = id.getAndIncrement();

  for (String arg : tableNames) {
      String url = (String) prop.get(arg + ".url");
      String user = (String) prop.get(arg + ".user");
      String password = (String) prop.get(arg + ".password");
      String driver = (String) prop.get(arg + ".driver");
      String suffix = (String) prop.get(arg + ".suffix");
      String sql = (String) prop.get(arg + ".sql");

      service.submit( new Task(id, url, user, password, driver, sql, suffix));
    }
}

此外,由于id计数器保留在内存中,您可能需要保留它,否则在重新启动应用程序后它将重置为0.