Android 中SQLite进行读写时,涉及的并发处理问题
2017-04-19 23:59
387 查看
相信做Android开发牵扯到SQLite数据库的时候,我们都知道数据库的CRUD都是不支持多线程操作的。当我们要使用多线程的时候,基本上就是为每个线程分配一个SQLiteOpenHelper对象来进行操作,但这样就会产生很大的性能问题,消耗更多的内存空间。
在这种情况下,我们一般就会只使用一个SQLiteOpenHelper对象来操作,如果我们要使用多线程,这时就需要注意SQLiteDataBase.close()调用的时机,因为你是使用的同一个引用,比如在一个线程中当一个Add操作结束后立刻关闭了数据库连接,而另一个现场中正准备执行查询操作,但此时db已经被关闭了,然后就会报下面的异常错误。
在这种情况下,我们一般会给CRUD添加一个 synchronized关键字,然后自己进行引用计数AtomicInteger。
关于AtomicInteger,它是一个提供原子操作的Integer的类,AtomicInteger是线程安全的,我们看一下它提供的接口
以上我们可以看到AtomicInteger的基本的使用,那么结合SQLiteOpenHelper的使用如下,
通过这种方式,我们就基本解决了多线程并发操作Sqlite时产生的问题。
本文参考了(http://www.cnblogs.com/wangmars/p/4530670.html),感谢
在这种情况下,我们一般就会只使用一个SQLiteOpenHelper对象来操作,如果我们要使用多线程,这时就需要注意SQLiteDataBase.close()调用的时机,因为你是使用的同一个引用,比如在一个线程中当一个Add操作结束后立刻关闭了数据库连接,而另一个现场中正准备执行查询操作,但此时db已经被关闭了,然后就会报下面的异常错误。
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:
在这种情况下,我们一般会给CRUD添加一个 synchronized关键字,然后自己进行引用计数AtomicInteger。
关于AtomicInteger,它是一个提供原子操作的Integer的类,AtomicInteger是线程安全的,我们看一下它提供的接口
//获取当前的值 public final int get() //取当前的值,并设置新的值 public final int getAndSet(int newValue) //获取当前的值,并自增 public final int getAndIncrement() //获取当前的值,并自减 public final int getAndDecrement() //获取当前的值,并加上预期的值 public final int getAndAdd(int delta)
public class AtomicIntegerDemo { public static void main(String[] args) { AtomicInteger ai=new AtomicInteger(0); int i1=ai.get(); v(i1); int i2=ai.getAndIncrement(); v(i2); } static void v(int i) { System.out.println("i : "+i); } }
以上我们可以看到AtomicInteger的基本的使用,那么结合SQLiteOpenHelper的使用如下,
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(); } }
通过这种方式,我们就基本解决了多线程并发操作Sqlite时产生的问题。
本文参考了(http://www.cnblogs.com/wangmars/p/4530670.html),感谢
相关文章推荐
- android createbitmap函数内存溢出,求解如何进行处理out of memory溢出问题
- android 如何显示软键盘中的搜索以及处理点击搜索却进行了两次操作问题
- android调用系统相机和相册进行拍照裁剪处理,解决不同安卓版本存在无法加载相册的问题,处理了是否有sd卡的存在的情况
- Android sqlite数据库并发访问问题处理
- 关于android开发BLE连接成功读写操作为什么gattback未回调的问题处理
- android 使用NDK进行图像处理(openCV)时的图像转换问题(灰度图显示)
- android createbitmap函数内存溢出,求解怎样进行处理out of memory溢出问题
- Android 数据库综述(二) 程序计算器与信号量来处理多线程并发问题
- android 关于蓝牙间通信,及RFID设备读写芯片问题的处理方案
- android图片显示(一) ———— 关于并发,乱序问题的处理
- 关于android Handler进行线程处理消息队列与线程队列线程无法停止的问题
- Web GIS 涉及到的常见Ajax框架 及 问题处理集锦
- csft安装过程中出错的问题及解决办法(目前仍然无法成功进行对中文的处理)
- 无法对jar进行签名,Android jarsigner问题
- ORACLE/JSP技术涉及日期、时间问题的处理
- ASP.NET 2.0中母版页中引用文件路径的问题(对原处理方法中的bug进行了修改)
- 关于数据库并发处理数据的问题
- 事务并发的问题及处理
- 在使用SSIS设计脚本时候,出现的在PostExecute之外不能锁定变量集合进行读写访问的问题的解决
- Loadrunner 进行SOCKET并发测试遇到问题