Android数据库并发操作解决思路
来源:互联网 发布:nginx lua 添加头部 编辑:程序博客网 时间:2024/05/15 23:45
数据库作为Android数据存储重要的一部分,相信很多应用中都会用到,面试也会遇到很多关于数据库的问题。实际开发中我没遇到过特别复杂的数据库使用,所以对这一块的优化没怎么研究过。
以前面试的时候被问到过这么一个问题:
面试官:数据库并发访问怎么处理?
我:给增删改查方法加锁。
面试官:那样会有什么问题?
我:效率低。
面试官:怎么解决?
我:不太清楚啊。。。
我一直认为Android开发不会涉及到数据库大量线程访问数据库的问题,所以方法加锁的效率问题是可以容忍的,搜索这个问题的解决方式,发现大家也都是粗暴的用synchronize
来解决。
我觉得即使优化也是在加锁的方式上优化,关于加锁的高级用法我没有研究过,所以一直没有太在意过这个问题(不要骂我不思进取不去学习高级用法。。。)。
后来不知道在哪看了什么东东受到了启发,我们可以用队列来解决这个问题啊!!
一个思路就是:创建一个单线程的线程池,所有的数据库操作都用这个线程池来操作
下面是我的demo,非常简单:
public class DBHelper extends SQLiteOpenHelper{ private static String DBName = "TestDB"; private static int DBVersion = 1; private SQLiteDatabase db; private static DBHelper INSTANCE; // 不用的时候需要关闭线程池 private ExecutorService pool; private DBHelper(Context context) { super(context, DBName, null, DBVersion); db = getReadableDatabase(); // 创建一个单线程池 pool = Executors.newSingleThreadExecutor(); } // 单例 public static DBHelper getInstance(Context context){ if(INSTANCE == null){ synchronized (DBHelper.class){ if (INSTANCE == null){ INSTANCE = new DBHelper(context.getApplicationContext()); } } } return INSTANCE; } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } // 模拟一个插入,参数随便写了,返回值和SQLiteDatabase的插入方法一样都是long类型,表示插入的id public long insert(final String param){ Future<Long> submit = pool.submit(new Callable<Long>() { @Override public Long call() throws Exception { // 休眠1秒,模拟耗时 Thread.sleep(1000); Log.e("lzw","插入 param: " + param); return 100L; } }); long id = -1; try { // 拿操作结果,这里会阻塞 id = submit.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } return id; }}
整个DBHelper是一个单例,在构造里实例化了一个单线程池,insert方法是表示插入,参数随便写了一个,我们通过pool.submit
方法把任务提交到了线程池进行执行,返回了一个Future
类型的变量,
后面调用Future
的get
方法可以拿到返回值,get
方法会阻塞,直到执行完call
方法里的内容并拿到返回值。关于ExecutorService
和Future
的使用不是本文重点,大家自行学习。
下面是测试Activity:
public class MainActivity extends AppCompatActivity { private TextView tv; private DBHelper helper; private int param = 0; static Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.content); helper = DBHelper.getInstance(this); findViewById(R.id.insert).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { param++; final int param2 = param; final long id = helper.insert("----> " + param2); handler.post(new Runnable() { @Override public void run() { tv.append(id + ":" + param2 + "\n"); } }); } }).start(); } }); }}
所有的操作都会逐条执行。
效果图如下:
以上就是所有的代码,只是讲了一下思路,用的时候大家根据自己的情况去封装就好了。
其实扩展一下,大家可以自己写一个生产者消费者模型也可以解决这个问题,核心思路和上面的方法都一样,就是一个阻塞队列,需要修改数据库的,把需求添加进队列,DBHelper从队列中不断取并操作数据库。
其实Handler的思路也是这么个套路。
不多说了,下面是代码地址:
https://github.com/dreamlizhengwei/DatabaseDemo
- Android数据库并发操作解决思路
- .Net高并发解决思路
- java高并发解决思路
- 解决Android中的SQLite数据库并发访问
- 解决android数据库并发访问异常
- 解决Android中的SQLite数据库并发访问
- 解决android数据库并发访问异常
- Android OOM解决思路
- Web应用高并发解决思路
- 提高服务器并发性能的解决思路
- 高并发量服务器性能解决思路
- java高并发的解决思路
- JAVA高性能高并发解决思路
- 数据库数据不一致解决思路
- 数据库并发操作
- 数据库并发操作
- 基本数据库并发操作
- 数据库的并发操作
- dex: 类加载过程
- @RequestParam @RequestBody @PathVariable 等参数绑定注解详解(转)
- 搞笑版费马大定理 CSU
- 数据结构之顺时针打印矩阵
- 洛谷 P2153 [SDOI2009]晨跑
- Android数据库并发操作解决思路
- Java-instanceof
- Information:Gradle tasks [:app:assembleDebug] Error:Execution failed for task ':app:transformClasses
- 常用正则
- 数组去重复 实现
- 深入分析volatile的实现原理
- 利用小技巧用于跟踪函数的进出过程
- js中return;、return true、return false;区别
- 利用资源文件实现窗体多语言