2014-01-08 28 views
1

我得到ANR当我尝试从数据库ANR消息与同步方法

public synchronized void insertNewObstacle(Obstacle newObstacle) { 

      SQLiteDatabase db = this.getWritableDatabase(); 

      db.execSQL("Insert into "+OBSTACLES_TABLE+" Values (' "+ 
        newObstacle.getLongitude() + "' , ' " + 
        newObstacle.getLatitude() + "' , ' " + 
        newObstacle.getDirection() + "' , ' " + 
        newObstacle.getType()  + "' , ' " + 
        newObstacle.getAddress() + "' , '" + 
        newObstacle.getSubmissionTime()  + "' , '" + 
        newObstacle.getSubmitterName() + "')" 
        ); 

      db.close(); 

     } 

的ANR是因为我从服务器获取数据,然后将其保存在本地 保存之后(获取数据线程1)我想获取保存的数据(线程2),这就是为什么我使 方法同步。

我的问题是:

为什么它不工作,我得到那个愚蠢的ANR消息?

或者我应该指定访问该方法的顺序吗?

1.i有asyncTaskLoader从服务器获取数据并保存它(线程1)。

2.asyncTask将数据发布到UI线程(线程2)。

痕迹文件:

at com.nilecode.matabat.AnonymousUser.DrawTypes(AnonymousUser.java:458) 

at com.nilecode.matabat.AnonymousUser$MainNotificationReceiver.onReceive 
(AnonymousUser.java:1085) 

at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:763) 

at android.os.Handler.handleCallback(Handler.java:730) 

at android.os.Handler.dispatchMessage(Handler.java:92) 

at android.os.Looper.loop(Looper.java:137) 

at android.app.ActivityThread.main(ActivityThread.java:5103) 

at java.lang.reflect.Method.invokeNative(Native Method) 

at java.lang.reflect.Method.invoke(Method.java:525) 

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 

at dalvik.system.NativeStart.main(Native Method) 

"AsyncTask #3" prio=5 tid=32 WAIT 

| group="main" sCount=1 dsCount=0 obj=0xa57ed5e8 self=0xb8fcd4a0 

| sysTid=2608 nice=10 sched=0/0 cgrp=[fopen-error:2] handle=-1191480800 

| state=S schedstat=(21993697 71845945 80) utm=0 stm=1 core=0 

at java.lang.Object.wait(Native Method) 
    - waiting on <0xa57ed700> 
(a java.lang.VMThread) held by tid=32 (AsyncTask #3) 

at java.lang.Thread.parkFor(Thread.java:1205) 

at sun.misc.Unsafe.park(Unsafe.java:325) 

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) 

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await 
(AbstractQueuedSynchronizer.java:2019) 

at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 

at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) 

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) 

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 

at java.lang.Thread.run(Thread.java:841) 

"AsyncTask #2" prio=5 tid=29 WAIT 

| group="main" sCount=1 dsCount=0 obj=0xa615bb08 self=0xb8e5b228 

| sysTid=2578 nice=10 sched=0/0 cgrp=[fopen-error:2] handle=-1192800808 

| state=S schedstat=(29573221 22137266 67) utm=1 stm=1 core=0 

at java.lang.Object.wait(Native Method) 

- waiting on <0xa60b1a28> (a java.lang.VMThread) held by tid=29 (AsyncTask #2) 

at java.lang.Thread.parkFor(Thread.java:1205) 

at sun.misc.Unsafe.park(Unsafe.java:325) 

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) 

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await 
(AbstractQueuedSynchronizer.java:2019) 

at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 

at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) 

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) 

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 

at java.lang.Thread.run(Thread.java:841) 

"Binder_3" prio=5 tid=28 NATIVE 

| group="main" sCount=1 dsCount=0 obj=0xa5144ba0 self=0xb8dd33e0 

| sysTid=2574 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194498544 

| state=S schedstat=(3711612 4635252 33) utm=0 stm=0 core=0 
    #00 pc 0002cff4 
/system/lib/libc.so (__ioctl+20) 

at dalvik.system.NativeStart.run(Native Method) 

"RenderDrive" prio=5 tid=27 SUSPENDED 

| group="main" sCount=1 dsCount=0 obj=0xa52ffd40 self=0xb8cf1eb0 

| sysTid=2559 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194081904 

| state=S schedstat=(278861639 194938487 3193) utm=0 stm=27 core=1 
    #00 pc 0002ed67 
/system/lib/libc.so (__futex_syscall4+23) 

at java.lang.VMThread.sleep(Native Method) 

at java.lang.Thread.sleep(Thread.java:1013) 

at java.lang.Thread.sleep(Thread.java:995) 

at maps.p.b.c((null):-1) 

at maps.an.b.run((null):-1) 

"IntentService[Request New Dataset Service]" prio=5 tid=26 SUSPENDED 

| group="main" sCount=1 dsCount=0 obj=0xa60b9148 self=0xb8cce168 

| sysTid=2557 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1194331408 

| state=S schedstat=(22023302408 4429908617 55349) utm=209 stm=1992 core=0 
    #00 pc 0002ed67 
/system/lib/libc.so (__futex_syscall4+23) 

at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method) 

at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:734) 

at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754) 

at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64) 

at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674) 

at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1603) 

at com.nilecode.matabat.data.LocalCachedObstacles.insertNewObstacle(LocalCachedObstacles.java:74) 

at com.nilecode.matabat.data.LocalCachedObstacles.insertNewDataSet(LocalCachedObstacles.java:62) 

at com.nilecode.matabat.ServerAsyncLoader.loadInBackground(ServerAsyncLoader.java:162) 

at com.nilecode.matabat.RequestNewDataSetService.requestAndCacheNearByLocations 
(RequestNewDataSetService.java:134) 

回答

2

​​方法锁定对象本身。如果另一个线程持有该锁,例如通过运行相同对象的其他同步方法,您的呼叫将会阻塞,直到锁定可用。

将主UI线程锁定5秒或更长会导致ANR。

与sqlite同步是不必要的 - 数据库将处理它自己的锁定。但是,独占写入事务将阻止任何其他访问,并且会出现SQLITE_BUSY错误。

一般来说,如果只有一个线程访问它,sqlite的效果最好。你应该重新考虑你的设计。如果长时间运行的数据库操作不需要是原子操作,则可以将其分割为较短的部分。

0

ANR消息所示,当UI线程没有响应超过5秒(与设备而异)。我认为你是从UI线程中调用方法,该方法与你调用insertNewObstacle方法的同一个对象同步。

此外,为什么你使用两个单独的线程来写作和阅读?只需使用一个AsyncTask即可从网络获取数据并在doInBackground的UI线程上显示数据。

0

当ui花纹不会在5秒内收到任何回应时出现。从服务器获取数据并将其保存到数据库可以通过后台服务使用线程或仅使用服务来完成,为什么即时提示后台服务,以便线程可以轻松运行。还有更多来加载数据库中的数据我不认为你需要异步任务。

现在你为什么得到ANR?

所以你是使用两个异步任务,都是UI线程拦截器和一个依赖于其他。所以除非你的数据没有从服务器加载并保存到数据库中,否则你需要再次加载数据到ui异步任务。所以UI线程必须等待,直到它从服务器和数据加载数据到UI。异步任务得到了不同的用例,不要在这里使用它,并尽量避免同步块unnessasary。