最近开发中,需要再多线程中操作数据库,但是Android的sqlite数据库是不能多线程写读写的。
先看一下报的错误:

 android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode   at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)

看一下代码

public class DBTestActivity extends BaseActivity {    private Button mAddStudent_bt;    @Override    protected void initView() {        setContentView(R.layout.ac_dbtest);        mAddStudent_bt=(Button)findViewById(R.id.ac_add_student_bt);        mAddStudent_bt.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                addStudent();            }        });    }    private void addStudent() {        //模拟1000个线程 加入数据库        for(int i=0;i<1000;i++){            new Thread(){                @Override                public void run() {                    super.run();                    try {                        //随机休眠3秒以内的时间                        Thread.sleep((long) (Math.random( )*1000*3));                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                     Student s=new Student();                    s.setStudentAge("1");                    s.setStudentName("name:"+ new Date().getTime());                    StudentDao.getInstance().addStudent(s);                }             }.start();        }    }}public class StudentDao {     private static  volatile  StudentDao dao;       public static final String TAG="StudentDao";     private StudentDao(){     }    public static  StudentDao getInstance(){        if(dao==null){            synchronized (StudentDao.class){                if(dao==null){                    dao=new StudentDao();                 }            }        }        return dao;    }  //添加学生的方法,会在多个线程中调用    public void addStudent(Student student){         ContentValues contentValues=new ContentValues();        contentValues.put("s_id", UUID.randomUUID().toString());        contentValues.put("s_name", student.getStudentName());        contentValues.put("s_age",student.getStudentAge());         DbManager dBManager=new DbManager(BaseApp.getBaseApplicationContext());        SQLiteDatabase writableDatabase  = dBManager.getWritableDatabase();        long result=  writableDatabase.insertOrThrow("student",null,contentValues);//这里返回行号        Log.e(TAG, "执行的结果" +result+" "+Thread.currentThread().getName());        writableDatabase.close();    }}

为了解决这个问题,我把所有的写操作放在一个线程里,保证每次调用写操作都只有一个线程,那么所有的 写方法都必须枷锁。
另外翻了一下资料,发现这个sqlite 的锁是库级别的,所以当有多个线程的时候就会涉及到同步问题。
我在dao层写了一个单线程的线程池,所有的写的操作的方法在这个线程池里调用,就ok了。
代码如下

public class StudentDao {    private static volatile StudentDao dao;    private static ExecutorService singThread    public static final String TAG = "StudentDao";    private StudentDao() {    }    public static StudentDao getInstance() {        if (dao == null) {            synchronized (StudentDao.class) {                if (dao == null) {                    dao = new StudentDao();                    singThread= Executors.newSingleThreadExecutor();                }            }        }        return dao;    }    public void addStudent(final  Student student) {        Runnable runnable=new Runnable() {                @Override                public void run() {                    ContentValues contentValues = new ContentValues();                    contentValues.put("s_id", UUID.randomUUID().toString());                    contentValues.put("s_name", student.getStudentName());                    contentValues.put("s_age", student.getStudentAge());                    DbManager dBManager = new DbManager(BaseApp.getBaseApplicationContext());                    SQLiteDatabase writableDatabase = dBManager.getWritableDatabase();                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    long result = writableDatabase.insertOrThrow("student", null, contentValues);//这里返回行号                    Log.e(TAG, "执行的结果1  " + result + " " + Thread.currentThread().getName());                    writableDatabase.close();                }            };        singThread.execute(runnable);    }    }

简单测试了一下,还没有出现了报错的问题,可能是我的数据比较小吧,找个机会多用点数据再测试一下。这种做法只是想的到一个临时解决办法,并不能够做为方法放在项目里,如果有好的方案,可以留言告诉我一下,谢谢。

更多相关文章

  1. [Android] 图片JNI(C++\Java)高斯模糊 多线程
  2. android文件管理器--文件操作
  3. android中sqlite数据库操作
  4. Android 操作Sqlite
  5. SQLite多线程操作数据库
  6. Android 系统联系人操作
  7. PC&移动平台设备检测库(平台、版本、操作系统、方向)
  8. Android之文件操作

随机推荐

  1. 有关Android线程的学习
  2. 获取Android(安卓)SDK 源代码并在Eclipse
  3. Android(安卓)TextView属性详解
  4. android:windowSoftInputMode 介绍
  5. android的surfaceflinger原理讲解
  6. 【Android】 保存图片到系统图库, 并立即
  7. Android到Androidx记录
  8. Android开发规范:API接口通用设计规范
  9. EditText单击触发onclick事件处理
  10. Android深入浅出之Binder机制