1. Обзор
Когда мы работаем над многопоточными проектами, мы знаем, что если несколько потоков совместно используют объекты, которые не реализованы с учетом безопасности потоков , потоки могут вести себя неожиданно .
Многие из нас, возможно, страдали от проблем с потокобезопасностью. Итак, вопрос «Является ли этот класс потокобезопасным?» часто приходит на ум.
Приложение Java довольно часто обращается к реляционным базам данных через JDBC, а также использует многопоточность. В этом кратком руководстве мы обсудим, является ли java.sql.Connection
потокобезопасным.
2. Интерфейс java.sql.Connection
Когда мы получаем доступ к базам данных через JDBC из наших приложений, мы прямо или косвенно используем объекты java.sql.Connection
. Мы полагаемся на эти объекты подключения для выполнения операций с базой данных. Поэтому java.sql.Connection
— довольно важный тип в JDBC.
Также распространен сценарий, когда несколько потоков должны одновременно обращаться к базе данных. В результате мы часто слышим вопрос: «Является ли java.sql.Connection
потокобезопасным?»
В следующих нескольких разделах мы более подробно рассмотрим этот вопрос. Далее мы обсудим правильный подход к использованию объектов java.sql.Connection
среди нескольких потоков, чтобы несколько потоков могли одновременно обращаться к базе данных.
3. Безопасность потоков и java.sql.Connection
Прежде всего, давайте быстро поговорим о безопасности потоков . Потокобезопасность — это метод программирования. То есть это концепция, связанная с реализацией. Следовательно, мы можем использовать различные методы, чтобы сделать реализацию потокобезопасной — например, реализации без сохранения состояния, неизменяемые реализации и т. д.
Теперь давайте посмотрим на java.sql.Connection
. Во-первых, это интерфейс — он не содержит никакой реализации. Поэтому не имеет особого смысла спрашивать в общем: «Является ли java.sql.Connection
потокобезопасным?» Мы должны проверить классы, которые реализуют этот интерфейс, чтобы решить, является ли реализация потокобезопасной или нет.
Что ж, сразу возникает пара вопросов: Какие классы реализуют этот интерфейс? Являются ли они потокобезопасными?
Обычно мы не реализуем интерфейс java.sql.Connection
в коде нашего приложения. Драйверы JDBC будут реализовывать этот интерфейс , чтобы мы могли получить соединение с определенной базой данных, такой как SQL Server или Oracle.
Таким образом, потокобезопасность реализации Connection
полностью зависит от драйверов JDBC.
Далее в качестве примеров мы рассмотрим пару JDBC-драйверов баз данных.
4. Примеры реализации java.sql.Connection
Microsoft SQL Server и Oracle Database — два широко используемых продукта реляционных баз данных.
В этом разделе мы рассмотрим драйверы JDBC этих двух баз данных и обсудим, являются ли их реализации интерфейса java.sql.Connection
потокобезопасными.
4.1. Microsoft SQL-сервер
Класс драйвера Microsoft SQL Server, SQLServerConnection
, реализует интерфейс java.sql.Connection
и не является потокобезопасным, согласно его Javadoc:
> `SQLServerConnection` не является потокобезопасным, однако несколько инструкций, созданных из одного соединения, могут обрабатываться одновременно в параллельных потоках.
Таким образом, это означает, что мы не должны совместно использовать объект SQLServerConnection
между потоками, но мы можем совместно использовать операторы, созданные из одного и того же объекта SQLServerConnection
.
Далее давайте взглянем на другой известный продукт баз данных, Oracle Database.
4.2. База данных Oracle
Официальный драйвер Oracle JDBC реализует интерфейс java.sql.Connection
потокобезопасным способом.
Oracle заявляет о безопасности потоков своей реализации Connection
в своем официальном документе :
Драйверы Oracle JDBC обеспечивают полную поддержку и оптимизированы для приложений, использующих многопоточность Java… Однако Oracle настоятельно не рекомендует совместное использование соединения с базой данных несколькими потоками. Избегайте одновременного доступа нескольких потоков к соединению...
Что ж, основываясь на приведенном выше описании, мы можем сказать, что реализация соединения Oracle является потокобезопасной. Однако совместное использование объекта соединения несколькими потоками «настоятельно не рекомендуется» .
Итак, из примеров SQL Server и Oracle мы знаем, что нельзя предполагать, что реализация java.sql.Connection
является потокобезопасной. Затем мы можем спросить, каков правильный подход, если мы хотим, чтобы несколько потоков одновременно обращались к базе данных? Разберемся в следующем разделе.
5. Использование пула соединений
Когда мы обращаемся к базе данных из нашего приложения, нам нужно сначала установить соединение с базой данных. Это считается дорогостоящей операцией. Для повышения производительности обычно используется пул соединений .
Давайте быстро разберемся, как работает пул соединений в многопоточном сценарии.
Пул соединений содержит несколько объектов соединений. Мы можем настроить размер пула.
Когда нескольким потокам требуется одновременный доступ к базе данных, они запрашивают объекты соединения из пула соединений.
Если в пуле еще есть свободные соединения, поток получит объект соединения и начнет свои операции с базой данных. После того, как поток завершит свою работу, он вернет соединение в пул.
Если в пуле нет свободного соединения, поток будет ждать, пока объект соединения будет возвращен в пул другим потоком.
Таким образом, пул соединений позволяет нескольким потокам одновременно обращаться к базе данных, используя разные объекты соединения, вместо того, чтобы совместно использовать один и тот же объект .
Далее, таким образом, нам не нужно заботиться о том, является ли реализация интерфейса Connection
потокобезопасной.
6. Заключение
В этой статье мы обсудили часто задаваемый вопрос: является ли java.sql.Connection
потокобезопасным?
Поскольку java.sql.Connection
является интерфейсом, непросто предсказать, являются ли его реализации потокобезопасными.
Более того, мы решили, что пул соединений — это правильный способ обработки соединений, если нескольким потокам требуется одновременный доступ к базе данных.