Android Sqlite 数据库多线程操作
16lz
2021-01-23
最近开发中,需要再多线程中操作数据库,但是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); } }
简单测试了一下,还没有出现了报错的问题,可能是我的数据比较小吧,找个机会多用点数据再测试一下。这种做法只是想的到一个临时解决办法,并不能够做为方法放在项目里,如果有好的方案,可以留言告诉我一下,谢谢。
更多相关文章
- [Android] 图片JNI(C++\Java)高斯模糊 多线程
- android文件管理器--文件操作
- android中sqlite数据库操作
- Android 操作Sqlite
- SQLite多线程操作数据库
- Android 系统联系人操作
- PC&移动平台设备检测库(平台、版本、操作系统、方向)
- Android之文件操作