Сохраните один и тот же идентификатор в обеих таблицах в многопоточном коде.

Я начал работать над проектом, в котором у меня есть две таблицы в другой базе данных с разными схемами. Поэтому у меня будет два разных параметра подключения для подключения к базе данных. И после подключения к каждой базе данных мне нужно вставить в эти две таблицы, используя sql, указанный в соответствующей таблице.

И я должен вставить во все две таблицы или любую из них, используя JDBC, в зависимости от параметров командной строки. Это означает, что один поток будет вставляться в Table1 и Table2 или в любую из них.

Параметры командной строки: — Здесь 10 — количество потоков, 100 — количество задач, table1 и table2 — имена таблиц.

10 100 table1 table2

Ниже мой код. В этом коде произойдет следующее: предположим, если мы передаем только одну таблицу с именем table1, тогда она будет вставлена ​​в эту таблицу с помощью SQL, предназначенного для таблицы1.

А также мне нужно вставить одно и то же id как в table1, так и в table2, и что id передается как AtomicInteger в конструктор Task. Значит, если id is 1, то 1 id должно быть и в table1, и в 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));
        }
    }

Ниже представлен класс Task, реализующий интерфейс Runnable.

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 и id, если я выбираю как 1.

Тогда в обеих таблицах нет одного и того же идентификатора, то есть идентификатор 1 будет только в одной таблице либо table1, либо table2. Единственная причина, о которой я могу думать, это id это AtomicInteger, поэтому каждый раз он будет получать новый id для каждого потока. Есть ли способ использовать один и тот же идентификатор для вставки в каждую из таблиц? А затем убедитесь, что идентификатор равен PrimaryKey, поэтому каждый поток получит новый идентификатор, если он снова вставляется в эти таблицы.


person Community    schedule 10.02.2013    source источник
comment
Сделать свой счетчик статичным, чтобы он был только один? Конечно, тогда вы должны договориться о том, кто несет ответственность за его увеличение.   -  person Hot Licks    schedule 11.02.2013
comment
Спасибо за предложение. Итак, вы говорите, что я должен сделать это private final AtomicInteger id ; статическим в классе Task, верно? Я попробовал это, изменив на статический, как этот private static AtomicInteger id ;, но результат тот же, и он не работает. id 1 идет только в одну таблицу.   -  person    schedule 11.02.2013
comment
Как я уже сказал, вы должны согласиться, чтобы только один поток увеличивал его для каждой операции обновления. Остальные просто ссылаются на увеличенное значение.   -  person Hot Licks    schedule 11.02.2013
comment
Имеет смысл для меня. Итак, как я могу достичь этого? Любой образец примера заставит меня лучше понять. Спасибо   -  person    schedule 11.02.2013


Ответы (1)


Если я правильно вас понял, вы должны определить счетчик как статический, чтобы избежать дублирования 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 после перезапуска приложения.

person ericson    schedule 18.02.2013