用synchronized方法ANR留言留言、方法、synchronized、ANR

由网友(28.我还能坚持)分享简介:我得到ANR当我尝试从数据库中获取数据 公共同步无效insertNewObstacle(障碍newObstacle){            SQLiteDatabase分贝= this.getWritableDatabase();            db.execSQL(插入+ OBSTACLES_TABLE +...

我得到ANR当我尝试从数据库中获取数据

 公共同步无效insertNewObstacle(障碍newObstacle){            SQLiteDatabase分贝= this.getWritableDatabase();            db.execSQL(插入+ OBSTACLES_TABLE +VALUES('+                    newObstacle.getLongitude()+,+                    newObstacle.getLatitude()+,+                    newObstacle.getDirection()+,+                    newObstacle.getType()+,+                    newObstacle.getAddress()+,+                    newObstacle.getSubmissionTime()+,+                    newObstacle.getSubmitterName()+')                    );            db.close();        } 

的ANR是因为我从服务器获取数据,然后将其保存在本地保存(线程1)我试图获取已保存的数据(线程2)后,这就是为什么我做了该方法进行同步。

我的问题是:

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

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

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

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

痕迹文件:

 (AnonymousUser.java:458)在com.nile code.matabat.AnonymousUser.DrawTypes在com.nile code.matabat.AnonymousUser $ MainNotificationReceiver.onReceive(AnonymousUser.java:1085)在android.app.LoadedApk $ ReceiverDispatcher $ Args.run(LoadedApk.java:763) 在android.os.Handler.handleCallback(Handler.java:730)在android.os.Handler.dispatchMessage(Handler.java:92)在android.os.Looper.loop(Looper.java:137)在android.app.ActivityThread.main(ActivityThread.java:5103)在java.lang.reflect.Method.invokeNative(本机方法)在java.lang.reflect.Method.invoke(Method.java:525)在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)在dalvik.system.NativeStart.main(本机方法)AsyncTask的#3PRIO = 5 TID = 32 WAIT|组=主SCOUNT = 1 dsCount = 0 = OBJ自我0xa57ed5e8 = 0xb8fcd4a0| sysTid = 2608 =不错附表10 = 0/0 CGRP =的fopen错误:2] =办理-1191480800|状态= S schedstat =(21993697 71845945 80)UTM = 0 STM = 1核心= 0在java.lang.Object.wait(本机方法)   - 等待针对<&0xa57ed700 GT;(一java.lang.VMThread)由TID = 32(AsyncTask的#3)持有在java.lang.Thread.parkFor(Thread.java:1205)在sun.misc.Unsafe.park(Unsafe.java:325)在java.util.concurrent.locks.LockSupport.park(LockSupport.java:159)在java.util.concurrent.locks.AbstractQueuedSynchronizer中的$ ConditionObject.await(AbstractQueuedSynchronizer.java:2019)在java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)在java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073)在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:573)在java.lang.Thread.run(Thread.java:841)AsyncTask的#2PRIO = 5 TID = 29 WAIT|组=主SCOUNT = 1 dsCount = 0 = OBJ自我0xa615bb08 = 0xb8e5b228| sysTid = 2578 =不错附表10 = 0/0 CGRP =的fopen错误:2] =办理-1192800808|状态= S schedstat =(29573221 22137266 67)UTM = 1 STM = 1核心= 0在java.lang.Object.wait(本机方法) - 等待针对<&0xa60b1a28 GT; (一java.lang.VMThread)由TID = 29(AsyncTask的#2)持有在java.lang.Thread.parkFor(Thread.java:1205)在sun.misc.Unsafe.park(Unsafe.java:325)在java.util.concurrent.locks.LockSupport.park(LockSupport.java:159)在java.util.concurrent.locks.AbstractQueuedSynchronizer中的$ ConditionObject.await(AbstractQueuedSynchronizer.java:2019)在java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)在java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073)在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:573)在java.lang.Thread.run(Thread.java:841)Binder_3PRIO = 5 TID = 28 NATIVE|组=主SCOUNT = 1 dsCount = 0 = OBJ自我0xa5144ba0 = 0xb8dd33e0| sysTid = 2574 =不错附表0 = 0/0 CGRP =的fopen错误:2] =办理-1194498544|状态= S schedstat =(3711612 4635252 33)UTM = 0 STM = 0核心= 0  #00件0002cff4/system/lib/libc.so(__ioctl +20)在dalvik.system.NativeStart.run(本机方法)RenderDrivePRIO = 5 TID = 27悬浮 |组=主SCOUNT = 1 dsCount = 0 = OBJ自我0xa52ffd40 = 0xb8cf1eb0| sysTid = 2559 =不错附表0 = 0/0 CGRP =的fopen错误:2] =办理-1194081904|状态= S schedstat =(278861639 194938487 3193)UTM = 0 STM = 27核心= 1  #00件0002ed67/system/lib/libc.so(__futex_syscall4 + 23)在java.lang.VMThread.sleep(本机方法)在java.lang.Thread.sleep(Thread.java:1013)在java.lang.Thread.sleep(Thread.java:995)在maps.p.b.c((空): -  1)在maps.an.b.run((空): -  1)IntentService [申请新数据集服务]PRIO = 5 TID = 26悬浮|组=主SCOUNT = 1 dsCount = 0 = OBJ自我0xa60b9148 = 0xb8cce168| sysTid = 2557 =不错附表0 = 0/0 CGRP =的fopen错误:2] =办理-1194331408|状态= S schedstat =(22023302408 4429908617 55349)UTM = 209 STM = 1992核心= 0  #00件0002ed67/system/lib/libc.so(__futex_syscall4 + 23)在android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(本机方法)在android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:734)在android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)在android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)在android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)在android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1603)在com.nile code.matabat.data.LocalCachedObstacles.insertNewObstacle(LocalCachedObstacles.java:74)在com.nile code.matabat.data.LocalCachedObstacles.insertNewDataSet(LocalCachedObstacles.java:62)在com.nile code.matabat.ServerAsyncLoader.loadInBackground(ServerAsyncLoader.java:162)在com.nile code.matabat.RequestNewDataSetService.requestAndCacheNearByLocations(RequestNewDataSetService.java:134) 

解决方案

对象本身的同步法锁。如果另一个线程持有这个锁例如通过在同一个对象的其他一些方法同步运行,您的通话将被阻塞,直到锁可用。

阻断5 secods主UI线程以上导致ANR。

使用SQLite同步是没有必要的 - 数据库将处理它自己的锁定。然而,独占写交易将prevent与 SQLITE_BUSY 错误的任何其他访问。

一般情况下,SQLite的效果最好,如果只有一个线程访问它。你应该重新考虑你的设计。如果有,这并不需要是原子的长时间运行数据库操作,将其分割成较短的部分。

深入理解synchronized底层原理,一篇文章就够了

I get ANR when i try to get the data from the database

    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();

        }

The ANR happens because I'm getting the data from the server then save it locally after saving it(Thread 1) i'm trying to get the saved data(Thread 2) that's why i made the method synchronized.

My question is:

why it is not working and i'm getting that stupid ANR message?

or should i specify the order of accessing that method?

1.i have asyncTaskLoader for getting the data from the server and saving it(Thread 1).

2.asyncTask for posting the data to the UI Thread(Thread 2).

Traces file:

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)

解决方案

synchronized method locks on the object itself. If another thread is holding that lock e.g. by running in some other synchronized method of the same object, your call will block until the lock is available.

Blocking the main UI thread for 5 secods or more causes the ANR.

Synchronization with sqlite is not necessary - the database will handle it own locking. However, an exclusive write transaction will prevent any other access with SQLITE_BUSY error.

Generally, sqlite works best if only one thread is accessing it. You should rethink your design. If there's a long-running database operation that does not need to be atomic, split it into shorter parts.

阅读全文

相关推荐

最新文章