本文的目的是介绍SQLiteDatabase多线程锁定模式的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于AndroidDataBase被其他线程锁定、androidSQ
本文的目的是介绍SQLiteDatabase多线程锁定模式的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于Android DataBase被其他线程锁定、android SQLiteDatabase、android – SQLiteDatabase getWritableDatabase()无法正常工作、android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase的知识。
本文目录一览:- SQLiteDatabase多线程锁定模式
- Android DataBase被其他线程锁定
- android SQLiteDatabase
- android – SQLiteDatabase getWritableDatabase()无法正常工作
- android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase
SQLiteDatabase多线程锁定模式
我使用此类来管理与基础SQLiteDatabase的连接
public class BasicDataSource { protected DatabaseHandler dbHelper; protected volatile SQLiteDatabase readable_database; protected volatile SQLiteDatabase writable_database; protected Object read_lock = new Object(); protected Object write_lock = new Object(); protected Context context; protected BasicDataSource(Context ctx) { dbHelper = DatabaseHandler.getInstance(ctx); getReadableDatabase(); dbHelper.onCreate(getWritableDatabase()); this.context = ctx; } public synchronized void close() { dbHelper.close(); } protected void closeInsertHelpers(InsertHelper... helpers) { for (InsertHelper ih : helpers) { if (ih != null) ih.close(); } } protected SQLiteDatabase getReadableDatabase() { synchronized (read_lock) { if (readable_database == null || !readable_database.isOpen()) { readable_database = dbHelper.getReadableDatabase(); } return readable_database; } } protected SQLiteDatabase getWritableDatabase() { synchronized (write_lock) { if (writable_database == null || !writable_database.isOpen()) { writable_database = dbHelper.getWritableDatabase(); } return writable_database; } } protected synchronized void open() throws SQLException { getReadableDatabase(); getWritableDatabase(); }}
它包含两个锁,一个用于读取,第二个用于写入。但是我仍然偶尔会遇到这种例外情况:
java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:299) at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) at java.util.concurrent.FutureTask.setException(FutureTask.java:124) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) at java.lang.Thread.run(Thread.java:856)Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882) at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627) at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313) at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804) at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164) at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57) at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264) at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560) at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315) at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) ... 4 moreandroid.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882) at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627) at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313) at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804) at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164) at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57) at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264) at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560) at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315) at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) at java.lang.Thread.run(Thread.java:856)
这意味着,在尝试获取getWritableDatabase中的锁定时,数据库以某种方式被锁定。
我的SQLiteOpenHelper是单例模式,并且DataSources仅使用BasicDataSource作为父类。
我可以做些什么来避免在显示的代码中出现SQLiteDatabaseLockedException?
答案1
小编典典在SQLite中,可以有任意多个读取器,但是任何写入器都会阻止所有其他读取器和写入器。
读者和作家都必须使用一个锁。
请注意,只要您实际访问数据库,就必须保持锁定。
如果要支持多个阅读器,请使用实现的锁ReadWriteLock
,例如ReentrantReadWriteLock
。像这样:
class MyData { private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public Data ReadSomething(int id) { r.lock(); try { Cursor c = readableDatabase.query(...); return c.getString(0); } finally { r.unlock(); } } public void ChangeSomething(int id, int value) { w.lock(); try { writeableDatabase.update(...); } finally { w.unlock(); } }}
Android DataBase被其他线程锁定
在代码中,我在启动应用程序时只打开一次数据库,并在那里设置了我的Application类变量的引用,以便我可以从代码的任何部分访问数据库,这很好.
问题是:我可以访问数据库,但我无法启动事务.它没有给我任何异常,但sqliteDatabaseWrite.isDbLockedByOtherThreads()返回TRUE.此外,在logcat中有一条警告消息:
WARN/sqliteDatabase(19006): database lock has not been available for
30 sec. Current Owner of the lock is 1. Continuing to wait in thread:
14
任何解决方案?
解决方法
sqliteDatabase.setTransactionSuccessful(); sqliteDatabase.endTransaction();
谢谢.
android SQLiteDatabase
SQLiteDatabase
[功能]
SQLiteDatabase 是关于数据库操作的 可用于 insert delete update query 等操作可惜美中不足的是:
1. 其不支持创建数据库
2. 其不支持版本更新 或者说其不知道如何做 因为具体数据的差异
鉴于以上的缺陷 有一个辅助类可以完成上面功能 那就是:SQLiteOpenHelper
[代码]
1. 定义 SQLiteOpenHelper 并完成 创建 更新 功能
- publicclassDBHelper extendsSQLiteOpenHelper {
- publicstaticfinalString TB_NAME = "mycountry";
- publicstaticfinalString ID = "_id";
- publicstaticfinalString COUNTRY = "country";
- publicstaticfinalString CODE = "code";
- publicDBHelper(Context context, String name,
- CursorFactory factory,intversion) {
- super(context, name, factory, version);
- }
- publicvoidonCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE IF NOT EXISTS "
- + TB_NAME + " ("
- + ID + " INTEGER PRIMARY KEY,"
- + COUNTRY + " VARCHAR,"
- + CODE + " INTEGER)");
- }
- publicvoidonUpgrade(SQLiteDatabase db,
- intoldVersion, intnewVersion) {
- //TODO 删除数据库之前 做数据备份
- db.execSQL("DROP TABLE IF EXISTS "+TB_NAME);
- onCreate(db);
- }
- }
2. 从 SQLiteOpenHelper 得到 SQLiteDatabase 的实例
- DBHelper helper = newDBHelper(this, DB_NAME, null, VERSION);
- SQLiteDatabase db = helper.getWritableDatabase();
3. SQLiteDatabase 的一些操作:
* 插入数据:
- ContentValues values = newContentValues();
- values.put(DBHelper.COUNTRY, "中国");
- values.put(DBHelper.CODE, 86);
- db.insert(DBHelper.TB_NAME,DBHelper.ID, values);
* 改动数据
- db.insert(DBHelper.TB_NAME,DBHelper.ID,null);
- values.clear();
- values.put(DBHelper.COUNTRY, "意大利");
- values.put(DBHelper.CODE, 39);
- db.update(DBHelper.TB_NAME, values,DBHelper.ID + " = 2",null);
* execSQL 执行 SQL 语言
- db.execSQL("INSERT INTO "
- + DBHelper.TB_NAME + "("
- + DBHelper.COUNTRY + ","
- + DBHelper.CODE + ") VALUES "
- + "('' 洪都拉斯 '',504)");
* 查询数据
- Cursor c = db.query(DBHelper.TB_NAME,null,null,null,null,null,
- DBHelper.CODE+" DESC");
* 删除数据所有数据
- db.delete(DBHelper.TB_NAME,null,null);
数据库的生成 调用 getWiterAbleDatabase getReadAbleDatabase 生成数据库 i
android 嵌入式数据库 为单用户数据库 所以 可以不调用 db.close () 来关闭数据库这样反而可以提高性能
android – SQLiteDatabase getWritableDatabase()无法正常工作
02-15 08:36:13.097: I/sqliteDatabaseCpp(404): sqlite returned: error
code = 1,msg = near “null”: Syntax error,
db=/data/data/com.lifeApp/databases/contactsManager
在我的代码的第157行.这是该方法下的部分
getAllContacts()
无效的代码是
sqliteDatabase db = this.getWritableDatabase();
完整示例:
package com.lifeApp; import android.content.Context; import android.database.sqlite.sqliteDatabase; import android.database.sqlite.sqliteOpenHelper; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.database.Cursor; public class DatabaseHandler extends sqliteOpenHelper { // All Static variables // Database Version private static final int DATABASE_VERSION = 1; // Database Name private static final String DATABASE_NAME = "contactsManager"; // Contacts table name private static final String TABLE_CONTACTS = "contacts"; // Contacts Table Columns names private static final String KEY_ID = "id"; private static final String FirsTNAME = "firstname"; private static final String LASTNAME = "lastname"; private static final String PASSWORD = "password"; private static final String EMAIL = "email"; private static final String KEY_PH_NO = "phone_number"; private static final String KEY_NAME = null; public DatabaseHandler(Context context) { super(context,DATABASE_NAME,null,DATABASE_VERSION); } // Creating Tables @Override public void onCreate(sqliteDatabase db) { String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," + FirsTNAME + " TEXT," + LASTNAME + " TEXT," + PASSWORD + " TEXT" + EMAIL + " TEXT" + KEY_PH_NO + " TEXT" + ")"; db.execsql(CREATE_CONTACTS_TABLE); } // Upgrading database @Override public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { // Drop older table if existed db.execsql("DROP TABLE IF EXISTS " + TABLE_CONTACTS); // Create tables again onCreate(db); } /** * All CRUD(Create,Read,Update,Delete) Operations */ // Adding new contact void addContact(Contact contact) { sqliteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME,contact.getName()); // Contact Name values.put(FirsTNAME,contact.getFirstname()); values.put(LASTNAME,contact.getLastname()); values.put(EMAIL,contact.getEmail()); values.put(PASSWORD,contact.getpassword()); values.put(KEY_PH_NO,contact.getPhoneNumber()); // Contact Phone // Inserting Row db.insert(TABLE_CONTACTS,values); db.close(); // Closing database connection } // Getting single contact Contact getContact(int id) { sqliteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(TABLE_CONTACTS,new String[] { KEY_ID,KEY_NAME,KEY_PH_NO },KEY_ID + "=?",new String[] { String.valueOf(id) },null); if (cursor != null) cursor.movetoFirst(); Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4),cursor.getString(5),cursor.getString(6)); // return contact return contact; } // Getting All Contacts public List<Contact> getAllContacts() { List<Contact> contactList = new ArrayList<Contact>(); // Select All Query String selectQuery = "SELECT * FROM " + TABLE_CONTACTS; sqliteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery,null); // looping through all rows and adding to list if (cursor.movetoFirst()) { do { Contact contact = new Contact(); contact.setID(Integer.parseInt(cursor.getString(0))); contact.setFirstname(cursor.getString(1)); contact.setLastname(cursor.getString(2)); contact.setPassword(cursor.getString(3)); contact.setEmail(cursor.getString(4)); // Adding contact to list contactList.add(contact); } while (cursor.movetoNext()); } // return contact list return contactList; } // Updating single contact public int updateContact(Contact contact) { sqliteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME,contact.getName()); values.put(FirsTNAME,contact.getLastname()); values.put(PASSWORD,contact.getpassword()); values.put(EMAIL,contact.getEmail()); values.put(KEY_PH_NO,contact.getPhoneNumber()); // updating row return db.update(TABLE_CONTACTS,values,KEY_ID + " = ?",new String[] { String.valueOf(contact.getID()) }); } // Deleting single contact public void deleteContact(Contact contact) { sqliteDatabase db = this.getWritableDatabase(); db.delete(TABLE_CONTACTS,new String[] { String.valueOf(contact.getID()) }); db.close(); } // Getting contacts Count public int getContactsCount() { String countQuery = "SELECT * FROM " + TABLE_CONTACTS; sqliteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery(countQuery,null); cursor.close(); // return count return cursor.getCount(); } }
解决方法
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," + FirsTNAME + " TEXT," + LASTNAME + " TEXT," + PASSWORD + " TEXT" <== + EMAIL + " TEXT" <== + KEY_PH_NO + " TEXT" + ")"; db.execsql(CREATE_CONTACTS_TABLE);
android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase
我应该使用哪种方法?基于我见过的示例代码,我首先使用sqliteOpenHelper创建数据库,但在需要使用数据库时调用sqliteDatabase.openDatabase.
解决方法
关于SQLiteDatabase多线程锁定模式的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android DataBase被其他线程锁定、android SQLiteDatabase、android – SQLiteDatabase getWritableDatabase()无法正常工作、android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase等相关内容,可以在本站寻找。
本文标签: