如何使用AsyncTask正确管理锁

时间:2014-08-05 00:50:03

标签: android json android-asynctask

我有一个Android应用程序,我需要从服务器(可能会失败)重复获取JSON,显示信息,并允许用户更改服务器的地址。似乎示例here可以解决这个问题,因为我可以异步地尝试在doInBackground中获取我的JSON,并根据计时器调用onProgressUpdate中的runAgain(),如果用户更改服务器地址,我可以调用terminateTask()并启动一个新的GetDataFromServerTask。但是,当我在onProgressUpdate中调用runAgain()时,我总是得到IllegalMonitorStateException。如果在onProgressUpdate中检查isHeldByCurrentThread(),则结果为false。所以任何人都可以扩展这个例子来确定为什么我似乎没有获得锁定?或者如果有更好的方法来完成我的任务,请随意提出。谢谢!

编辑:使用上述参考添加完整代码。 (此版本仅用于测试,并不执行上述所有操作。)

package com.testing.asynctest;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        new GetDataFromServerTask().execute();
    }

    class GetDataFromServerTask extends AsyncTask<Void, Void, Void> {

        private final ReentrantLock lock = new ReentrantLock();
        private final Condition tryAgain = lock.newCondition();
        private volatile boolean finished = false;

        @Override
        protected Void doInBackground(Void... params) {

            try {
                lock.lockInterruptibly();
                try {
                    do {
                        // This is the bulk of our task, request the data, and put in "result"
                        Log.d("MyActivity", "Perform Main Task");

                        // Return it to the activity thread using publishProgress()
                        publishProgress();

                        // At the end, we acquire a lock that will delay
                        // the next execution until runAgain() is called..
                        Log.d("MyActivity", "Acquiring Lock");
                        tryAgain.await();
                        Log.d("MyActivity", "Lock was released");

                    } while(!finished);

                } finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... result)
        {
            // Treat this like onPostExecute(), do something with result

            // This is an example...
            runAgain();
        }

        public void runAgain() {
            // Call this to request data from the server again
            if ( lock.isHeldByCurrentThread() ) {
                Log.d("MyActivity", "Releasing Lock");
                tryAgain.signal();
            } else {
                Log.d("MyActivity", "Lock Not Held by Thread");
            }
        }

        public void terminateTask() {
            // The task will only finish when we call this method
            finished = true;
            lock.unlock();
        }

        @Override
        protected void onCancelled() {
            // Make sure we clean up if the task is killed
            terminateTask();
        }
    }
}

LOG输出显示我没有我期望的锁。

 com.testing.asynctest D/MyActivity﹕ Perform Main Task
 com.testing.asynctest D/MyActivity﹕ Acquiring Lock
 com.testing.asynctest D/MyActivity﹕ Lock Not Held by Thread

我理解IllegalMonitorStateException的含义,并使用isHeldByCurrentThread进行测试以验证我没有持有锁。我只是不明白这个例子有什么问题导致我没有锁定。谢谢!

1 个答案:

答案 0 :(得分:0)

IllegalMonitorStateException上的documentation

  

当监视器未执行监视操作时,抛出该异常   处于正确的状态,例如当一个线程试图退出a时   监视它不拥有。

您还没有提供足够的信息(即相关代码),但我猜您正在尝试在没有锁定的对象上等待()/ notify()。