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)