亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android SQLite3多線程操作問題研究總結

 更新時間:2015年03月23日 09:02:04   投稿:junjie  
這篇文章主要介紹了Android SQLite3多線程操作問題研究總結,本文總結了SQLite3是否支持多線程、SQLiteDatabase的同步鎖、多線程讀數據庫等問題,需要的朋友可以參考下

最近做項目時在多線程讀寫數據庫時拋出了異常,這自然是我對SQlite3有理解不到位的地方,所以事后仔細探究了一番。

1.關于getWriteableDataBase()和getReadableDatabase()的真正作用
getWriteableDataBase()其實是相當于getReadableDatabase()的一個子方法,getWriteableDataBase()是只能返回一個以讀寫方式打開的SQLiteDatabase的引用,如果此時數據庫不可寫時就會拋出異常,比如數據庫的磁盤空間滿了的情況。而getReadableDatabase()一般默認是調用getWriteableDataBase()方法,如果數據庫不可寫時就會返回一個以只讀方式打開的SQLiteDatabase的引用,這就是二者最明顯的區(qū)別。

關鍵源碼如下:

public synchronized SQLiteDatabase getWritableDatabase() {
  if (mDatabase != null) {
    if (!mDatabase.isOpen()) {
    // darn! the user closed the database by calling mDatabase.close()
    mDatabase = null;
    } else if (!mDatabase.isReadOnly()) {
    return mDatabase; // The database is already open for business
    }
  }
... ...

public synchronized SQLiteDatabase getReadableDatabase() {
  if (mDatabase != null) {
    if (!mDatabase.isOpen()) {
    // darn! the user closed the database by calling mDatabase.close()
    mDatabase = null;
    } else {
    return mDatabase; // The database is already open for business
    }
  }
 ... ...
  try {
    return getWritableDatabase();
  }
... ...

2.SQLiteDatabase的同步鎖

其實在只使用一個SQLiteDatabase的引用時,SQLiteDatabase對CRUD操作都會加上一個鎖(因為是db文件,所以精確至數據庫級),這就保證了在同一時間你只能進行一項操作,無論是不是在同一個線程中,這就導致了如果你在程序中對SQLiteOpenHelper使用了單例模式,那么你對數據庫讀寫進行任何的優(yōu)化操作都是"徒勞"。

3.多線程讀數據庫

仔細看源碼你會發(fā)現(xiàn),在數據庫操作中只有add,delete,update會調用lock(),而query()是不會調用的,但是在加載數據時,調用了SQLiteQuery的fillWindow方法,而該方法依然會調用SQLiteDatabase.lock(),所以要想真正的實現(xiàn)多線程讀數據庫,只能每個線程使用各自的SQLiteOpenHelper對象進行讀操作,這樣就可避開同步鎖。關鍵源碼如下:

/* package */ int fillWindow(CursorWindow window,
  int maxRead, int lastPos) {
  long timeStart = SystemClock.uptimeMillis();
  mDatabase.lock();
  mDatabase.logTimeStat(mSql, timeStart, SQLiteDatabase.GET_LOCK_LOG_PREFIX);
  try {... ...

4.多線程讀寫

實現(xiàn)多線程讀寫的關鍵是enableWriteAheadLogging屬性,這個方法 API Level 11添加的,也就是所3.0以上的版本就基本不可能實現(xiàn)真正的多線程讀寫了。簡單的說通過調用enableWriteAheadLogging()和disableWriteAheadLogging()可以控制該數據是否被運行多線程讀寫,如果允許,它將允許一個寫線程與多個讀線程同時在一個SQLiteDatabase上起作用。實現(xiàn)原理是寫操作其實是在一個單獨的log文件,讀操作讀的是原數據文件,是寫操作開始之前的內容,從而互不影響。當寫操作結束后讀操作將察覺到新數據庫的狀態(tài)。當然這樣做的弊端是將消耗更多的內存空間。

5.多線程寫

這個就不用多想了,SQLite壓根不支持,如果實在有需求可以使用多個數據庫文件。

6.備注

(1)你有沒有想SQLite最多支持多少個數據庫連接,其實在官方API文檔(enableWriteAheadLogging ()方法)中給出了最精確的答案:The maximum number of connections used to execute queries in parallel is dependent upon the device memory and possibly other properties.就是看你有多少內存,但是我感覺這話說的有點大,是不?哈哈。

(2)當你在多線程中只使用一個SQLiteDatabase的引用時,需要格外注意你SQLiteDataBase.close()調用的時機,因為你是使用的同一個引用,比如在一個線程中當一個Add操作結束后立刻關閉了數據庫連接,而另一個現(xiàn)場中正準備執(zhí)行查詢操作,但此時db已經被關閉了,然后就會報異常錯誤。此時一般有三種解決方案,①簡單粗暴給所有的CRUD添加一個 synchronized關鍵字;②永遠不關閉數據庫連接,只在最后退出是關閉連接。其實每次執(zhí)行getWriteableDataBase()或getReadableDatabase()方法時,如果有已經建立的數據庫連接則直接返回(例外:如果舊的連接是以只讀方式打開的,則會在新建連接成功的前提下,關閉舊連接),所以程序中將始終保持有且只有一個數據庫連接(前提是單例),資源消耗的很少。③可以自己進行引用計數,簡單示例代碼如下:

//打開數據庫方法
public synchronized SQLiteDatabase openDatabase() {
if (mOpenCounter.incrementAndGet() == 1) {
 // Opening new database
 try {
 mDatabase = sInstance.getWritableDatabase();
 } catch (Exception e) {
 mDatabase = sInstance.getReadableDatabase();
 }
 }
return mDatabase;
}

//關閉數據庫方法
public synchronized void closeDatabase() {
 if (mOpenCounter.decrementAndGet() == 0) {
 // Closing database
 mDatabase.close();
 }
 }

 (3)還有一些比較好的習慣和常識,例如關閉Cursor,使用Transaction,SQLite存儲數據時其實不區(qū)分類型,以及SQLite支持大部分標準SQL語句,增刪改查語句都是通用的等等。

相關文章

  • Android webView如何輸出自定義網頁

    Android webView如何輸出自定義網頁

    這篇文章主要介紹了Android webView如何輸出自定義網頁,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Android自定義View仿大眾點評星星評分控件

    Android自定義View仿大眾點評星星評分控件

    這篇文章主要為大家詳細介紹了Android自定義View仿大眾點評星星評分控件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 簡單好用的Adapter---ArrayAdapter詳解

    簡單好用的Adapter---ArrayAdapter詳解

    這篇文章主要介紹了簡單好用的Adapter---ArrayAdapter詳解,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 簡述angular自定義過濾器在頁面和控制器中的使用

    簡述angular自定義過濾器在頁面和控制器中的使用

    這篇文章主要介紹了簡述angular自定義過濾器在頁面和控制器中的使用的相關資料,需要的朋友可以參考下
    2016-09-09
  • Flutter自定義下拉刷新時的loading樣式的方法詳解

    Flutter自定義下拉刷新時的loading樣式的方法詳解

    Flutter中的下拉刷新,我們通常RefreshIndicator,可以通過color或strokeWidth設置下拉刷新的顏色粗細等樣式,但如果要自定義自己的widget,RefreshIndicator并沒有暴露出對應的屬性,那如何修改呢,文中給大家介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • 解析Android框架之Volley源碼

    解析Android框架之Volley源碼

    我們知道Volley是在2013年Google I/O大會上推出了一個新的網絡通信框架,他的設計目的就是為了那些請求數據量不是特別大,但是又是特別頻繁的網絡操作非常適合。但是對于數據量較大的請求,比如說下載一個較大的文件,Volley可能相比于其他的框架,就有點不足了。
    2021-06-06
  • Android開發(fā)實現(xiàn)各種圖形繪制功能示例

    Android開發(fā)實現(xiàn)各種圖形繪制功能示例

    這篇文章主要介紹了Android開發(fā)實現(xiàn)各種圖形繪制功能,結合實例形式分析了Android圖形繪制常用的組件、函數使用方法及相關注意事項,需要的朋友可以參考下
    2017-09-09
  • Android通過ExifInterface判斷Camera圖片方向的方法

    Android通過ExifInterface判斷Camera圖片方向的方法

    今天小編就為大家分享一篇關于Android通過ExifInterface判斷相機圖片朝向的方法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Android App端與PHP Web端的簡單數據交互實現(xiàn)示例

    Android App端與PHP Web端的簡單數據交互實現(xiàn)示例

    本篇文章主要介紹了Android App端與PHP Web端的簡單數據交互實現(xiàn)示例,詳細的介紹了交互的代碼,非常具有實用價值,有興趣的可以了解一下
    2017-10-10
  • c++ mk文件出錯Jni調用產生java.lang.UnsatisfiedLinkError錯誤解決方法

    c++ mk文件出錯Jni調用產生java.lang.UnsatisfiedLinkError錯誤解決方法

    錯誤產生在我把方法從c語言轉為c++語言后產生的,后來檢查到這種錯誤是因為mk文件出錯,加載c文件和加載c++的文件所用的代碼不一樣,下面請看
    2013-11-11

最新評論