数据库插入失败引出的多线程问题
来源:互联网 发布:什么是敏捷软件开发 编辑:程序博客网 时间:2024/04/29 14:11
昨天遇到一个奇葩问题, 一组不重复的数据在插入数据库的时候
数据 a 出现unique failed , 但是插入成功
数据 b 没有报错, 但是插入失败
并且发现for循环内都遍历不到数据b , 但是for循环外是可以打印到它的
就像鬼打墙一样搞了我6个小时查不出原因,
最后发现只要在插入前进行一次排序就不会出错, 虽然不明白原理, 姑且先这么把问题解决掉
<span style="font-size:14px;">public boolean insertClauseList(List<Clause> clauses,int stdNo){// Collections.sort(clauses, new Comparator<Clause>() {// @Override// public int compare(Clause lhs, Clause rhs) {// if (lhs.parentno != rhs.parentno) {// return lhs.parentno - rhs.parentno;// } else {// return lhs.sortby - rhs.sortby;// }// }// }); SQLiteDatabase db = helper.getWritableDatabase(); long insertResult; ArrayList<String> errorList = new ArrayList<>(); for (Clause clause : clauses) { ContentValues values = new ContentValues(); values.put(DBConstants.CLAUSE_NO,clause.no); values.put(DBConstants.CLAUSE_PARENTNO,clause.parentno); values.put(DBConstants.CLAUSE_SORTBY,clause.sortby); values.put(DBConstants.CLAUSE_CHAPTER,clause.chapter); values.put(DBConstants.CLAUSE_CAPTION,clause.caption); values.put(DBConstants.CLAUSE_GENRE,clause.genre); values.put(DBConstants.CLAUSE_ISCATALOG,clause.iscatalog); values.put(DBConstants.CLAUSE_EXPLAIN,clause.explain); values.put(DBConstants.CLAUSE_MANDATORY,clause.mandatory); values.put(DBConstants.CLAUSE_FAILING,clause.failing); values.put(DBConstants.CLAUSE_STDID,clause.stdid); values.put(DBConstants.CLAUSE_STDNO,stdNo); insertResult = db.insert(DBConstants.TB_CLAUSE, null, values); if (insertResult == -1) errorList.add(BaseApp.getContext().getString(R.string.ommitted,clause.no)); if (clause.parentno == 0){ LogUtils.w("根节点保存结果__"+insertResult); } } if (errorList.size() == 0){ return true; }else { LogUtils.w("errorlist--"+errorList); return false; } }</span>
今天换了一台新的6.0测试机, 运行到相同的位置的时候报出CurrentModifyException, 才想起这个鬼打墙是多线程访问相同资源造成的
原因是我在网络获取数据后, 把同一个list分别传递给主线程展示和子线程进行插入数据库操作
并且, 主线程的界面在展示前对list进行了一次排序, 而此时子线程正在遍历list插入数据
结果是 子线程插入数据a完成后 主线程将数据a和数据b位置对换了, 子线程访问到该位置时读取的还是数据a的内存地址, 数据b因此没有访问到
新的机器由于性能好, 多个线程操作数据的速度更快, 才暴露出问题
由此进行如下改进
1. 避免传递源数据, 使用ArrayList(List)构造复制一个list后传递
2. 对数据进行增删改的操作放到分发之前完成, 分发后只进行遍历
问题解决
0 0
- 数据库插入失败引出的多线程问题
- 关于数据库 约束或主外键约束的插入失败问题
- #引出的各种问题
- lambda引出的问题
- 使用Tokyo Cabinet数据库,引出的编译问题。
- 数据库插入的问题?
- 多线程——问题引出以及解决方法
- db2数据库的Clob域出现字符串过长插入失败的问题
- hibernate插入数据库失败
- 数据库插入数据失败
- 指针初始化引出的问题
- z-order引出的问题
- 二分查找引出的问题
- z-order引出的问题
- z-order引出的问题
- ORA-12519引出的问题
- PhotoCamera引出的一个问题
- 关于_ATL_MIN_CRT引出的问题
- spring整合mybatis遇到的问题
- Trie 树
- Python 核心编程笔记_Chapter_4_Note_2 内建函数(built-in functions)
- SVN常用命令说明
- java.text.NumberFormat 工具类
- 数据库插入失败引出的多线程问题
- Java源代码分析之LinkedList
- __init__(self),self,super,继承杂谈
- pgpool复制和负载均衡
- 支持向量机SMO算法求解过程分析
- JAVA POST请求远程HTTP接口
- 比特币简介1
- android中不同类之间的数据通信之接口回调
- Linux驱动关联丢失处理