最近在做一个Android项目, 为了改善用户体验,把原先必须让用户“等待”的过程改成在新线程中异步执行。但是这样做遇到了多个线程同时需要写Sqlite数据库,导致操作数据库失败。
本人对JAVA并不熟悉,只接触了2个多月(纯粹为了Android项目, 才开始接触JAVA), 在网上搜了一下, 发现JAVA在线程同步方面提供的功能相对于C#真少,只找到synchronized关键字, 而且还不提供timeout机制, 不过经过测试, 至少解决了目前的需求。
问题需求:
1. Android中, 对Sqlite数据库操作, 需要自己实现一个继承自SQLiteOpenHelper的类
2. 实现类中, 对数据库read操作不需要同步(提高效率)
3. 实现类中, 所有对数据库写操作, 必须要同步
解决方法:
定义一个private final static byte[] _writeLock = new byte[0]; 作为写锁
static 保证多个实例之间, 使用的是同一个对象(同一把锁)
final 保证锁对象不会被修改
测试代码:
01 | package com.yushiro; |
02 | |
03 | |
04 | public class multiThreadTest { |
05 | |
06 | private final static byte [] _writeLock = new byte [ 0 ]; |
07 | private static int _syncInt = 0 ; |
08 | public void Method1(){ |
09 | synchronized (_writeLock) { |
10 | StringBuffer sb = new StringBuffer(); |
11 | sb.append(Thread.currentThread().getName()); |
12 | sb.append( " Method1 " ); |
13 | sb.append(_syncInt); |
14 | _syncInt++; |
15 | sb.append( " --> " ); |
16 | sb.append(_syncInt); |
17 | System.out.println(sb.toString()); |
18 | } |
19 | } |
20 | |
21 | public void Method2(){ |
22 | synchronized (_writeLock) { |
23 | StringBuffer sb = new StringBuffer(); |
24 | sb.append(Thread.currentThread().getName()); |
25 | sb.append( " Method2 " ); |
26 | sb.append(_syncInt); |
27 | _syncInt++; |
28 | sb.append( " --> " ); |
29 | sb.append(_syncInt); |
30 | System.out.println(sb.toString()); } |
31 | } |
32 | |
33 | public void Method3(){ |
34 | synchronized (_writeLock) { |
35 | this .Method1(); |
36 | this .Method2(); |
37 | } |
38 | } |
39 | } |
01 | package com.yushiro; |
02 | |
03 | |
04 | public class MainTest { |
05 | |
06 | |
07 | public static void main(String[] args) { |
08 | |
09 | Thread t2= new Thread1(); |
10 | Thread t1= new Thread2(); |
11 | Thread t3 = new Thread3(); |
12 | t1.start(); |
13 | t2.start(); |
14 | t3.start(); |
15 | } |
16 | |
17 | private static class Thread2 extends Thread { |
18 | public void run() { |
19 | multiThreadTest tmp = new multiThreadTest(); |
20 | while ( true ) { |
21 | |
22 | |
23 | try { |
24 | Thread.sleep( 30000 ); |
25 | tmp.Method1(); |
26 | } catch (InterruptedException e) { |
27 | // TODO Auto-generated catch block |
28 | e.printStackTrace(); |
29 | } |
30 | |
31 | //System.out.println(y); |
32 | } |
33 | } |
34 | } |
35 | |
36 | private static class Thread1 extends Thread { |
37 | public void run() { |
38 | multiThreadTest tmp = new multiThreadTest(); |
39 | while ( true ) { |
40 | |
41 | |
42 | try { |
43 | Thread.sleep( 100 ); |
44 | tmp.Method2(); |
45 | Thread.sleep( 100 ); |
46 | tmp.Method1(); |
47 | } catch (InterruptedException e) { |
48 | // TODO Auto-generated catch block |
49 | e.printStackTrace(); |
50 | } |
51 | |
52 | //System.out.println(y); |
53 | } |
54 | } |
55 | } |
56 | private static class Thread3 extends Thread { |
57 | public void run() { |
58 | multiThreadTest tmp = new multiThreadTest(); |
59 | while ( true ) { |
60 | |
61 | |
62 | try { |
63 | Thread.sleep( 100 ); |
64 | tmp.Method3(); |
65 | } catch (InterruptedException e) { |
66 | // TODO Auto-generated catch block |
67 | e.printStackTrace(); |
68 | } |
69 | |
70 | //System.out.println(y); |
71 | } |
72 | } |
73 | } |
74 | |
75 | } |
Method3()是为了测试自旋锁
参考: