JDBC и Threading - PullRequest
       16

JDBC и Threading

3 голосов
/ 01 августа 2009

У меня есть программа, которая должна запрашивать базу данных через заданный интервал, и с полученными записями она выполняет какое-то действие, а затем снова обновляет таблицу.

Я использую ExecutorService для запуска потоков, но мне интересно, должен ли каждый поток получить свое собственное соединение (потому что ему нужно обновить базу данных) или я могу использовать то же соединение, которое использовал для запроса начальных результатов?

Может ли пул соединений работать, на Oracle 9i.

Ответы [ 2 ]

10 голосов
/ 01 августа 2009

Вы всегда должны использовать отдельное соединение для отдельных потоков, так как драйверы не являются потокобезопасными таким образом. Вам может помочь пул соединений, поскольку он позволяет безопасно использовать соединение повторно.

Вы также можете сделать шаблон запроса-отправки - если я правильно понимаю вашу проблему - где один поток отвечает за запрос и запуск N потоков, которые могут обновить базу данных - у всех из которых есть отдельные объекты подключения.

Вы также можете рассмотреть возможность выполнения пакетного обновления с помощью PreparedStatement, чтобы потоки не сталкивались друг с другом в терминах блокировок строк и таблиц, используя следующую структуру:

  • 1 поток запросов
  • Потоки обработки NCPU
  • 1 поток обновления пакета

Как мини-дб-форк-соединение.

Редактировать

Примеры того, как выполнить пакетное обновление с помощью Pstmt:

PreparedStatement pstmt = connection.prepareStatement(
    "UPDATE table SET field=? WHERE id=?");
for (int i = 0; i < 100; i++) {
    pstmt.setInt(1, i * i);
    pstmt.setInt(2, i);
    pstmt.addBatch();
}
pstmt.executeBatch();
pstmt.close();

Или вы можете запросить очередь в цикле, куда поступают запросы на обновление из потоков обработки:

class WhatToUpdate {
    public int id;
    public int value;
}
Queue<WhatToUpdate> queue = new LinkedBlockingQueue<WhatToUpdate>();

PreparedStatement pstmt = connection.prepareStatement(
    "UPDATE table SET field=? WHERE id=?");

int poisons = THE_NUMBER_OF_PROCESSING_THREADS;
while (true) {
    WhatToUpdate record == queue.take();
    if (record == null) { // poison pill
        if (--poisons <= 0) {
            break;
        }
    }
    pstmt.setInt(1, record.value);
    pstmt.setInt(2, record.id);
    pstmt.addBatch();
}
pstmt.executeBatch();
pstmt.close();
2 голосов
/ 01 августа 2009

Если вы посмотрите на код для Oracle jdbc OracleConnection и OraclePreparedStatement, большинство важных методов синхронизированы, поэтому они «потокобезопасны». Использование одного Connection в нескольких потоках не даст вам наибольшей эффективности, так как каждый поток должен будет ждать выполнения операций Connection и PreparedStatement (особенно execute), прежде чем выполнять свои собственные действия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...