zoukankan      html  css  js  c++  java
  • (原创)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;
        }

    上面提供一个使用方法,现在项目中使用这种方法关于数据库的操作从未没有出现并发的问题,大家可以尝试一下。

  • 相关阅读:
    SQL Server ->> Natively Compiled Stored Procedures(本地编译存储过程)
    Linux ->> <user_name> not in the sudoers file. This incident will be reported.
    Linux ->> Ping命令
    Linux ->> UBuntu 14.04 LTE下主机名称和IP地址解析
    Linux ->> UBuntu ->> Could not get lock /var/lib/dpkg/lock
    Linux ->> scp命令复制对端机器上的文件/文件夹
    Linux ->> UBuntu 14.04 LTE下安装Hadoop 1.2.1(伪分布模式)
    Linux ->> UBuntu 14.04 LTE下设置静态IP地址
    .Net ->> iTextSharp工具读取PDF文本内容
    oracle case用法
  • 原文地址:https://www.cnblogs.com/wangmars/p/4530670.html
Copyright © 2011-2022 走看看