参考http://blog.csdn.net/sdsxleon/article/details/18259973  很好

https://github.com/2point0/Android-Database-Locking-Collisions-Example 示例

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=333473

http://bbs.51cto.com/thread-990260-1.html

用事务,速度会很会

方案1:

SQLite实质上是将数据写入一个文件,通常情况下,在应用的包名下面都能找到xxx.db的文件,拥有root权限的手机,可以通过adb shell,看到data/data/packagename/databases/xxx.db这样的文件。

我们可以得知SQLite是文件级别的锁:多个线程可以同时读,但是同时只能有一个线程写。Android提供了SqliteOpenHelper类,加入Java的锁机制以便调用。

如果多线程同时读写(这里的指不同的线程用使用的是不同的Helper实例),后面的就会遇到android.database.sqlite.SQLiteException: database is locked这样的异常。
对于这样的问题,解决的办法就是keep single sqlite connection,保持单个SqliteOpenHelper实例,同时对所有数据库操作的方法添加synchronized关键字。

完美解决sqlite的 database locked 或者是 error 5: database locked 问题

/**
* @FileName : DatabaseHelper.java
* @ProjectName : SqlitePractice
* @PakageName : com.sqlitepractice.database
* @Author : Brant
* @CreateDate : 2012-12-16
*/
package com.sqlitepractice.database; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
import android.util.Log; /**
* @Module : 隶属模块名
* @Comments : 描述
* @Author : Brant
* @CreateDate : 2012-12-16
* @ModifiedBy : Brant
* @ModifiedDate: 2012-12-16
* @Modified:
* 2012-12-16: 实现基本功能
*/
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String TAG = "DatabaseHelper";
private static final String DB_NAME = "practice.db";
private final static String DB_TABLE_APP = "app";
private static final int DB_VERSION = 1;
private static final String DB_CREATE_TABLE_APP = "CREATE TABLE " + DB_TABLE_APP + "(" + APP_COLUMNS._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + APP_COLUMNS.PACKAGE_NAME
+ " NTEXT NOT NULL," + APP_COLUMNS.APP_NAME + " NTEXT NOT NULL," + APP_COLUMNS.APP_NAME_PINYIN + " NTEXT,"
+ APP_COLUMNS.CLASS_NAME + " NTEXT NOT NULL);"; private static DatabaseHelper mInstance; protected DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
} public synchronized static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context);
}
return mInstance;
} public synchronized static void destoryInstance() {
if (mInstance != null) {
mInstance.close();
}
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE_TABLE_APP);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub } public synchronized int getCount() {
Log.d(TAG, "getCount");
int count = -1;
Cursor c = getReadableDatabase().query(DB_TABLE_APP, null, null, null, null, null, null);
if (c.moveToFirst()) {
count = c.getCount();
}
c.close();
c = null;
return count;
} public synchronized void insert(String packageName, String appLabel, String pinyin, String className) {
Log.d(TAG, "insert");
ContentValues values = new ContentValues(4);
values.put(APP_COLUMNS.PACKAGE_NAME, packageName);
values.put(APP_COLUMNS.APP_NAME, appLabel);
values.put(APP_COLUMNS.APP_NAME_PINYIN, pinyin);
values.put(APP_COLUMNS.CLASS_NAME, className);
getWritableDatabase().insert(DB_TABLE_APP, null, values);
} public static class APP_COLUMNS implements BaseColumns {
public static final String PACKAGE_NAME = "package_name";
public static final String APP_NAME = "app_name";
public static final String APP_NAME_PINYIN = "app_name_pinyin";
public static final String CLASS_NAME = "class_name"; public static final int ID_INDEX = 0;
public static final int PACKAGE_NAME_INDEX = 1;
public static final int APP_NAME_INDEX = 2;
public static final int APP_NAME_PINYIN_INDEX = 3;
public static final int CLASS_NAME_INDEX = 4;
} }

  

package com.sqlitepractice;

import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu; import com.sqlitepractice.database.DatabaseHelper; public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private static int sThreadCounter = 0; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final int threadCount = 8;
final List<Thread> allThreads = new ArrayList<Thread>(threadCount);
DatabaseHelper helper = DatabaseHelper.getInstance(this);
for (int i = 0; i < threadCount; i++) {
allThreads.add(new DbInsertThread(helper, 50, sThreadCounter++));
}
for (int i = 0; i < threadCount; i++) {
allThreads.add(new FastSelectThread(helper, sThreadCounter++, 50));
} for (Thread thread : allThreads) {
thread.start();
} // Wait for all threads to complete before running
for (Thread thread : allThreads) {
try {
thread.join();
Log.i(thread.getName(), "collected");
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted", e);
}
} Log.i(TAG, "All threads finished!");
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
} class DbInsertThread extends Thread {
private final String TAG = DbInsertThread.class.getSimpleName(); private final DatabaseHelper mDbHelper;
private int mRunCount; DbInsertThread(DatabaseHelper helper, int runCount, int id) {
setName(String.format("%1$s-%2$d", TAG, id)); mDbHelper = helper;
mRunCount = runCount;
Log.i(getName(), helper.toString());
} @Override
public void run() {
for (int i = 0; i < mRunCount; i++) {
try {
mDbHelper.insert("com.xx.xxxx", "测试", "ceshi", "MainActivity");
} catch (Exception e) {
Log.e(getName(), "Insert failed!!!, stopping writes", e);
break;
}
} Log.i(getName(), "finished!"); }
} class FastSelectThread extends Thread {
private final String TAG = FastSelectThread.class.getSimpleName(); private final DatabaseHelper mHelper;
private final int mCount; FastSelectThread(DatabaseHelper helper, int id, int selectCount) {
setName(String.format("%1$s-%2$d", TAG, id)); mHelper = helper;
mCount = selectCount > 0 ? selectCount : 50; Log.i(getName(), helper.toString());
} @Override
public void run() {
int count = 0;
while (count < mCount) {
mHelper.getCount(); Log.i(getName(), "start wait");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
} Log.i(getName(), "end wait"); count++;
} Log.i(getName(), "finished!");
}
} }

  

Android多线程操作sqlite(Sqlite解决database locked问题)的更多相关文章

  1. Android多线程操作,as快捷键笔记

    Android studio 快捷键 cmd+p 快速查看该方法的参数定义 * * option + shift +上下 快速移动上下行 * * cmd + e 显示最近操作的文件 * * cmd + ...

  2. Android多线程操作sqlite(Sqlite解决database locked问题)(2)使用事务处理的效果

    问题场景描述: 在页面中用到了ViewPager控件,ViewPager中的内容分别是两个ListView,两个ListView的数据都来自本地数据库(先从网络下载数据,然后更新本地数据库),在实际的 ...

  3. android 多线程

    本章讲述在android开发中,多线程的应用.多线程能够处理耗时的操作并优化程序的性能.本章主要介绍知识点,AsyncTask,Java线程池,ThreadPoolExecutor线程池类.本章案例只 ...

  4. sqlite:多线程操作数据库“database is locked”解决方法(二)

    上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大 ...

  5. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

    1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...

  6. Sqlite 数据库出现database disk image is malformed报错的解决方法

    软件用的是Sqlite数据库,昨天还好好的,今天开机登录软件报错:database disk image is malformed 用Sqlite Expert Personal 重建索引,发现其中一 ...

  7. [Android] Android 使用 Greendao 操作 db sqlite(2)-- 封装DaoUtils类

    继续接上文: Android 使用 Greendao 操作 db sqlite(1)-- 直接在MainActivity中调用 布局文件同上文一致,这里就不贴了. 一.封装DaoUtils类 User ...

  8. [Android] Android 使用 Greendao 操作 db sqlite(1)-- 直接在MainActivity中调用

    继续接上文: Android 使用 Greendao 操作 db sqlite 布局文件: activity_test_green.xml <?xml version="1.0&quo ...

  9. [Android] Android 使用 Greendao 操作 db sqlite

    Android 使用 Greendao 操作 db sqlite GreenDAO是一个开源的安卓ORM框架,能够使SQLite数据库的开发再次变得有趣.它减轻开发人员处理低级数据库需求,同时节省开发 ...

随机推荐

  1. Java并发-ConcurrentModificationException原因源码分析与解决办法

    一.异常原因与异常源码分析 对集合(List.Set.Map)迭代时对其进行修改就会出现java.util.ConcurrentModificationException异常.这里以ArrayList ...

  2. c# 软件绑定网卡mac的实用

    一:网上搜c# 绑定网卡Mac 有好多信息,其中有篇分为几种方法获取mac 的方法,结果获得到的是一个list 队列的信息,信息获取到所有的物理网卡,无线网卡,蓝牙,隧道的网卡物理地址.对与软件绑定物 ...

  3. BZOJ1123或洛谷3469 [POI2008]BLO-Blockade

    BZOJ原题链接 洛谷原题链接 若第\(i\)个点不是割点,那么只有这个点单独形成一个连通块,其它点依旧连通,则答案为\(2\times (n-1)\). 若第\(i\)个点是割点,那么去掉这个点相关 ...

  4. LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

    #2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  5. 没加载redis类,却可以实例化redis

    原因:phpinfo里面已有redis扩展

  6. ERROR - abandon connection, open stackTrace

    项目采用的是阿里巴巴的druid连接池,配置文件中有个removeAbandoned的配置(意义是某个连接如果超过设置的连接活动时间的话,连接会被强制关掉),但是因为爬虫中某些连接会长时间处于活动状态 ...

  7. easyui下拉框过滤优化

    项目中有个需求:编辑combobox的输入域会自动检索匹配项,当没有任何匹配项时,将combobox重置为初始状态. 处理方式:重写输入域的blur事件,判断当前值是否为加载的数据集的子集,如果不是则 ...

  8. c#使用Stopwatch来计算时间间隔

    今天要记录一个接口的耗时情况,就要求去写一段测试各个代码运行时间的方法,于是就加了这么一段代码.原来的做法是在代码执行之前和之后获取系统时间,然后相减.被改成了使用c#里的Stopwatch来计算时间 ...

  9. Git/Github的使用并与Eclipse整合(zz)

    Git/Github的使用并与Eclipse整合 您的评价:          收藏该经验       Git简介 Git是一个免费的.分布式的版本控制工具,或是一个强调了速度快的源代码管理工具.每一 ...

  10. import this

    import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than ...