Корректно это использование PreparedStatements в Потоке в Java?

Я - все еще старшекурсник только время рабочей детали и таким образом, я всегда пытаюсь знать о лучших способах сделать вещи. Недавно я должен был записать программу для работы, где основной поток программы породит потоки "задачи" (для каждой записи "задачи" дб), который выполнил бы некоторые операции и затем обновил бы запись, чтобы сказать, что это закончилось. Поэтому мне были нужны объект соединения с базой данных и объекты PreparedStatement в или доступный объектам ThreadedTask.

Это примерно, что я закончил тем, что писал, создает a PreparedStatement объект на поток отходы? Я думал статичный PreparedStatments мог создать условия состязания...

Thread A stmt.setInt();
Thread B stmt.setInt();
Thread A stmt.execute();  
Thread B stmt.execute();  

Версия A никогда не получает execed..

Действительно ли это ориентировано на многопотоковое исполнение? Создает и уничтожает PreparedStatement объекты, которые всегда являются тем же не огромные отходы?

public class ThreadedTask implements runnable {
    private final PreparedStatement taskCompleteStmt;

    public ThreadedTask() {
        //...
        taskCompleteStmt = Main.db.prepareStatement(...);
    }

    public run() {
        //...
        taskCompleteStmt.executeUpdate();
    }
}

public class Main {
    public static final db = DriverManager.getConnection(...);
}
8
задан Joachim Sauer 26 April 2010 в 13:19
поделиться

3 ответа

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

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

Не является ли создание и уничтожение неизменных объектов PreparedStatement огромной тратой?

Не совсем. Большая часть работы выполняется на сервере и будет кэшироваться и повторно использоваться там, если вы используете тот же оператор SQL. Некоторые драйверы JDBC также поддерживают кэширование операторов, так что даже дескриптор оператора на стороне клиента можно использовать повторно.

Однако вы можете увидеть существенные улучшения, используя пакетные запросы вместо (или в дополнение к) нескольких потоков. Подготовьте запрос один раз и запустите его для большого количества данных одним большим пакетом.

17
ответ дан 5 December 2019 в 05:44
поделиться

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

Тем не менее, вам не нужно беспокоиться о кешировании подготовленных заявлений. Об этой задаче позаботятся драйвер JDBC и БД. Лучше беспокойтесь об утечке ресурсов и сделайте свой JDBC-код как можно более надежным.

public class ThreadedTask implements runnable {
    public run() {
        Connection connection = null;
        Statement statement = null;
        try {
            connection = DriverManager.getConnection(url);
            statement = connection.prepareStatement(sql);
            // ...
        } catch (SQLException e) {
            // Handle?
        } finally {
            if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
            if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
        }
    }
}

Для повышения производительности подключения используйте пул подключений, например c3p0 (это, кстати, не означает, что вы можете изменить способ написания кода JDBC; всегда приобретайте и закрыть ресурсы в кратчайшей возможной области в блоке try-finally ).

7
ответ дан 5 December 2019 в 05:44
поделиться

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

5
ответ дан 5 December 2019 в 05:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: