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.微软SQL服务器
Microsoft SQL Server 驱动程序类 SQLServerConnection 实现了 java.sql.Connection 接口,并且根据其 Javadoc 不是线程安全的:
SQLServerConnection 不是线程安全的,但是从单个连接创建的多个语句可以在并发线程中同时处理。
因此,这意味着 我们不应该在线程之间共享 SQLServerConnection 对象,但我们可以共享从同一个 SQLServerConnection 对象创建的语句 。
接下来我们来看看另一个知名的数据库产品——Oracle数据库。
4.2.甲骨文数据库
官方Oracle JDBC驱动程序以线程安全的方式实现 java.sql.Connection 接口。
Oracle在其官方文档中声明了其 Connection 实现的线程安全性:
Oracle JDBC 驱动程序为使用 Java 多线程的应用程序提供全面支持并对其进行了高度优化……
然而,Oracle 强烈反对在多个线程之间共享数据库连接。避免允许多个线程同时访问连接......
好了,根据上面的描述,我们可以说Oracle的连接实现是线程安全的。但是, “强烈建议不要”在多个线程之间共享连接对象 。
因此,从 SQL Server 和 Oracle 示例中,我们知道我们不能假设 java.sql.Connection 实现是线程安全的。那么,我们可能会问,如果我们想要多个线程同时访问数据库,正确的做法是什么?让我们在下一节中弄清楚它。
5. 使用连接池
当我们从应用程序访问数据库时,我们首先需要建立与数据库的连接。这被认为是一项昂贵的操作。为了提高性能,通常我们会使用连接池。
让我们快速了解一下连接池在多线程场景下是如何工作的。
一个连接池保存多个连接对象。我们可以配置池的大小。
当多个线程需要并发访问数据库时,它们会向连接池请求连接对象。
如果池中还有空闲连接,线程将获取连接对象并开始其数据库操作。线程完成工作后,会将连接返回到池中。
如果池中没有空闲连接,该线程将等待另一个线程将连接对象返回到池中。
因此, 连接池允许多个线程使用不同的连接对象同时访问数据库,而不是共享同一个连接对象 。
进一步,这样我们就不用关心 Connection 接口的实现是否是线程安全的。
六,结论
在本文中,我们讨论了常见问题: java.sql.Connection 线程安全吗?
由于 java.sql.Connection 是一个接口,因此很难预测其实现是否是线程安全的。
此外,我们还指出,如果多个线程需要同时访问数据库,则连接池是处理连接的正确方法。