我有一个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进行测试以验证我没有持有锁。我只是不明白这个例子有什么问题导致我没有锁定。谢谢!
答案 0 :(得分:0)
IllegalMonitorStateException
上的documentation:
当监视器未执行监视操作时,抛出该异常 处于正确的状态,例如当一个线程试图退出a时 监视它不拥有。
您还没有提供足够的信息(即相关代码),但我猜您正在尝试在没有锁定的对象上等待()/ notify()。