(原创)android Sqlite多线程访问异常解决方案
在开发Android的程序的时候sqlite数据库是经常用到的;在多线程访问数据库的时候会出现这样的异常:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: 或java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
这样的异常信息,Sqlite 自身是不支持多线程同时操作的,下面呢我们给出一个解决方案并列出一些项目中用到的代码。
我们会用到AtomicInteger,一个提供原子操作的Integer的类。因为Android 依托强大的jdk在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口,由此我们可以做一个DatabaseManager 这样的类,具体代码见下面的代码块:
public class DatabaseManager {
private AtomicInteger mOpenCounter = new AtomicInteger();
private static DatabaseManager instance;
private static SQLiteOpenHelper mDatabaseHelper;
private SQLiteDatabase mDatabase;
public static synchronized void initializeInstance(SQLiteOpenHelper helper) {
if (instance == null) {
instance = new DatabaseManager();
mDatabaseHelper = helper;
}
}
public static synchronized DatabaseManager getInstance(SQLiteOpenHelper helper) {
if (instance == null) {
initializeInstance(helper);
}
return instance;
}
public synchronized SQLiteDatabase getWritableDatabase() {
if(mOpenCounter.incrementAndGet() == 1) {
// Opening new database
mDatabase = mDatabaseHelper.getWritableDatabase();
}
return mDatabase;
}
public synchronized SQLiteDatabase getReadableDatabase() {
if(mOpenCounter.incrementAndGet() == 1) {
// Opening new database
mDatabase = mDatabaseHelper.getReadableDatabase();
}
return mDatabase;
}
public synchronized void closeDatabase() {
if(mOpenCounter.decrementAndGet() == 0) {
// Closing database
mDatabase.close();
}
}
在我们进行关闭数据库的时候判断
mOpenCounter.decrementAndGet() == 0 (更新器管理的给定对象的字段的当前值为0)的时候才正式关闭数据库,就不会出现上述异常。 用方式呢,在我们操作数据库逻辑代码中如下使用
首相要取得
mDatabaseManager = DatabaseManager.getInstance(mContext);
对象
/***
* 判断表中是否有值
*/
public boolean isExistTabValus() {
boolean flag = false;
SQLiteDatabase db = mDatabaseManager.getReadableDatabase();//获取一个可读的数据库对象
Cursor curcor = null;
try {
curcor = db.rawQuery("select * from tab ", null);
while (curcor.moveToNext()) {
if (curcor.getCount() > 0) {
flag = true;
}
}
} catch (Exception e) {
Log.e(TAG, "isExistTabValus error");
} finally {
if (curcor != null) {
curcor.close();
}
mDatabaseManager.closeDatabase();//关闭数据库
}
return flag;
}
上面提供一个使用方法,现在项目中使用这种方法关于数据库的操作从未没有出现并发的问题,大家可以尝试一下。
(原创)android Sqlite多线程访问异常解决方案的更多相关文章
- CoreData和SQLite多线程访问时的线程安全
关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常 ...
- SQLite多线程写锁文件解决方案
在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题. 思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作:其他线程来写时,需要先检测是否有进程正在 ...
- 关于CoreData和SQLite多线程访问时的线程安全问题
数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两 ...
- CoreData和SQLite多线程访问时的线程安全问题
数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两 ...
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- 多线程访问winform控件出现异常的解决方法
一. 多线程访问winform控件出现异常的解决方法 1. 问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...
- IOS 使用FMDB多线程访问数据库 及databaseislocked的问题
原理:文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写.在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译s ...
- Android实现网络访问
Android实现网络访问 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 1) 熟练使用HttpURLConnection访问WebServ ...
- [转] c#中 多线程访问winform控件
原文 c#中多线程访问winform控件的若干问题小结 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来解决这个问题,下面我将详细的 ...
随机推荐
- zepto - push
var arr = ['1', '2', '3', '4']; arr.push('qwe'); console.log(arr);
- iOS开发工具——网络封包分析工具Charles
简介 Charles是在Mac下常用的截取网络封包的工具,在做iOS开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析.Charles通过将自己设置成系统的网络访问代理服务器,使 ...
- java中反射机制通过字节码文件对象获取字段和函数的方法
pclass = Class.forName("get_class_method.Person"); //Field ageField = pclass.getField(&quo ...
- MongoDB入门二:基本概念
前言 工欲善其事必先利其器.在学习MongoDB之前,需要对MongoDB的一些基本概念有系统的了解. 所以,本篇文章主要介绍MongoDB的一些基本概念,这些概念的定义均来自<MongoDB权 ...
- Unity3D 敌人AI 和 动画( Animator )系统的实例讲解
在这个实例中,我们要做一些敌人AI的简单实现,其中自动跟随和动画是重点,我们要达到的目标如下: 1.敌人能够自动跟随主角 2.敌人模型一共有四个动作:Idle(空闲) Run(奔跑) Attack(攻 ...
- JS&CSS文件请求合并及压缩处理研究(三)
上篇我们进行了一些代码方面的准备工作.接下来的逻辑是:在View页面解析时,通过 Html.AppendResFile 方法添加的资源文件,我们需要按照分组.优先级,文件名等条件,对其路径进行合并.具 ...
- TinyFox在VS2015上的调试器
这个一个TinyFox在VS2015上的调试工具 : 开源了 https://github.com/maxzhang1985/TinyFoxDEBUG 开发这个工具的初衷,是想更便捷的调试Nancy ...
- 【第三课】ANR和OOM——贪快和贪多的后果(下)
Out of Mana,法力耗尽. 内存就像法力,耗尽了就什么都不能做了.有时候一个应用程序占用了太大的内存,超过了Android系统为你规定的限制,那么系统就会干掉你,以保证其他app有足够的内存. ...
- mysql 在row模式下truncate 与 delete 二进制日志记录的差异
二进行日志的格式为row mysql> show variables like 'binlog_format'; +---------------+-------+ | Variable_nam ...
- .net 读书笔记
好书不能只读一遍,这两天又翻看了一遍<你必须知道的.NET>,重温了下基础,重温了下经典,简单记录了下来. 内存分配:CLR 管理内存的区域,主要有三块,分别为: 线程的堆栈,用于分配值类 ...