DBUtil数据库连接单例 —— 简单不简单
单例大概是我最早产生明确模式意识的设计模式,因为它足够简单粗暴,目的足够明确。
单例么,就是不管怎么访问,都返回一个单一实例就好了,我最早应用在数据库的DBUtil中。
public class DBUtils
{ //驱动串
private final static String Driver="com.mysql.jdbc.Driver";
//连接串
private static String url="jdbc:mysql://"+ SysProperties.MYSQL_HOST+":"+SysProperties.MYSQL_PORT+"/"+SysProperties.MYSQL_NAME+"?autoReconnect=true&autoReconnectForPools=true";
//Connection
private static Connection conn; private DBUtils()
{
} public static Connection getConnection()throws Exception
{
url="jdbc:mysql://"+SysProperties.MYSQL_HOST+":"+SysProperties.MYSQL_PORT+"/"+SysProperties.MYSQL_NAME;
CE.lgInfo("url:" + url); if(conn==null || conn.isClosed())
{
conn=DriverManager.getConnection(url, SysProperties.MYSQL_USER, SysProperties.MYSQL_PWD);
} return conn;
} }
很完美,在我的小程序里跑了近两年。
可是有的时候检查订单,就会发现每个阶段的订单都有那么几块钱无论如何对不上。这一直是个幽灵bug,困扰许久。
知道有一天,检查日志的的时候发现,当一个数据库在访问数据库进行锁表的时候,被锁内容却被另一个操作修改掉了。于是,我第一次看到了线程的影子。
但是那时候我对线程的理解完全不够透彻,只是模糊知道:
- 可能是有好几个请求同时访问了这个方法;
- 在一个请求要new Connection的时候,将new未new之际,另一个请求插队了,也挤进来了;
- 第二个请求一看,哦,没有connection,我也new一个,其实此时第一个请求已经在new了,只不过还没new出来而已;
- 结果就出来了两个Connection,单例?呵呵……
然后知道了有个关键字叫synchronized, 好,改。
public static synchronized Connection getConnection()throws Exception
{
url="jdbc:mysql://"+SysProperties.MYSQL_HOST+":"+SysProperties.MYSQL_PORT+"/"+SysProperties.MYSQL_NAME;
CE.lgInfo("url:" + url); if(conn==null || conn.isClosed())
{
conn=DriverManager.getConnection(url, SysProperties.MYSQL_USER, SysProperties.MYSQL_PWD);
} return conn;
}
于是变成了这样。于是,同一时间只有一个线程可以访问这个方法,其他人想访问,好,你等着吧,等我搞完你再上。
所有对该方法的请求被JVM强制排起了队,自然不会被new出来多个Connection了。
跑了半年,似乎不错。
但是后来忽然想,我之所以使用synchronized,是不想让他重复new,而不是不想让他重复访问。感觉就像什么呢,大家去生孩子,为了让医生好好工作,让大家都要排队进产房,这很正常,可是我现在除了让大家排队进产房,还让大家排队怀孕……这就扯淡了。
于是查资料,知道了synchronized不仅可以作用于方法,还可作用于区块。于是有了下面这个:
public static synchronized Connection getConnection()throws Exception
{
url="jdbc:mysql://"+SysProperties.MYSQL_HOST+":"+SysProperties.MYSQL_PORT+"/"+SysProperties.MYSQL_NAME;
CE.lgInfo("url:" + url); if(conn==null || conn.isClosed())
{
synchronized (DBUtil.class){
if(conn==null || conn.isClosed()){
conn=DriverManager.getConnection(url, SysProperties.MYSQL_USER, SysProperties.MYSQL_PWD);
}
}
} return conn;
}
只有为null的时候,才排队。为啥判断两次?更安全啊。
当然,后来知道了他有个更高大上的名字,称为“双重检查锁”。
所以,一个单例,真的简单么?可以用最快速的方法实现一个单例,也可以用相对更安全的方法实现一个单例。
如果你在面试,一个单例写下来,就知道你是一个菜鸟还是老手了。
DBUtil数据库连接单例 —— 简单不简单的更多相关文章
- Java获取Access数据库连接单例简单实例
Java在连接Access数据库时比较方便,不用导入第三方的jar包,jdk中内置的odbc可以完成Access数据库的访问,需要注意的是,我们首先要配置Access数据库的数据源,还要区分x86和x ...
- php进阶学习-单例设计模式
什么是单例模式(singleton)? 在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点. 单例模式的特点 一个类只有一个实例 私有克隆 ...
- C#中的简单工厂和单例
下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...
- 从一个简单的Java单例示例谈谈并发
一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...
- 从一个简单的Java单例示例谈谈并发 JMM JUC
原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这 ...
- GCD实现简单的单例类-Singletion
什么是单例模式 1.单例模式是一个类在系统中只有一个实例对象.通过全局的一个入口点对这个实例对象进行访问.在 iOS 开发中,单例模式是非常有用的一种设计模式.如 下图,是一个简单单例模式的 UML ...
- 简单介绍如何使用PowerMock和Mockito来mock 1. 构造函数 2. 静态函数 3. 枚举实现的单例 4. 选择参数值做为函数的返回值(转)
本文将简单介绍如何使用PowerMock和Mockito来mock1. 构造函数2. 静态函数3. 枚举实现的单例4. 选择参数值做为函数的返回值5. 在调用mock出来的方法中,改变方法参数的值 一 ...
- Java单例类的简单实现
对于java新手来说,单例类给我的印象挺深,之前一道web后台笔试题就是写单例类.*.*可惜当时不了解. 在大部分时候,我们将类的构造器定义成public访问权限,允许任何类自由创建该类的对象.但在某 ...
- Swift中简单的单例设计
import Foundation class Test: NSObject { // 提供单例实例 static let shareInstance = Test() // 私有化构造方法 over ...
随机推荐
- ABP文档 - 本地化
文档目录 本节内容: 简介 应用语言 本地化源 XML文件 注册XML本地化源 JSOn文件 注册JSON本地化源 资源文件 自定义源 获取一个本地文本 在服务端 在MVc控制器里 在MVC视图里 在 ...
- 多个Img标签之间的间隙处理方法
1.多个标签写在一行 <img src="/i/eg_tulip.jpg" alt="郁金香" height="100px"/> ...
- EntityFramework之DetectChanges's Secrets(三)(我为EF正名)
前言 对于应用程序开发者来说,通常不需要考虑太多对于Entity Framework中的变更追踪(change tracking),但是变更追踪和DetectChanges方法是栈的一部分,在这其中, ...
- 算法与数据结构(十七) 基数排序(Swift 3.0版)
前面几篇博客我们已经陆陆续续的为大家介绍了7种排序方式,今天博客的主题依然与排序算法相关.今天这篇博客就来聊聊基数排序,基数排序算法是不稳定的排序算法,在排序数字较小的情况下,基数排序算法的效率还是比 ...
- 算法与数据结构(九) 查找表的顺序查找、折半查找、插值查找以及Fibonacci查找
今天这篇博客就聊聊几种常见的查找算法,当然本篇博客只是涉及了部分查找算法,接下来的几篇博客中都将会介绍关于查找的相关内容.本篇博客主要介绍查找表的顺序查找.折半查找.插值查找以及Fibonacci查找 ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- C++随笔:.NET CoreCLR之GC探索(4)
今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...
- 不懂CSS的后端难道就不是好程序猿?
由于H5在移动端的发展如日中天,现在大部分公司对高级前端需求也是到处挖墙角,前端薪资也随之水涨船高,那公司没有配备专用的前端怎么办呢? 作为老板眼中的“程序猿” 前端都不会是非常无能的表现,那作为后端 ...
- C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程
前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...
- 【微信小程序开发】之如何获取免费ssl证书【图文步骤】
微信小程序要求所有网络请求都走ssl加密,因此我们开发服务端接口需要配置为https 这篇文章介绍一下如何 在 startssl 申请一个免费的ca证书. 1. 打开网站 https://www.s ...