我将全局静态对象定义为同步锁。
public static Object ConfirmationSynObj = new Object();
以下函数是我写的,但它抛出了IllegalMonitorStateException。
synchronized (Config.ConfirmationSynObj) {
new Thread(new Runnable() {
@Override
public void run() {
//this is a http request
appSignInfo = getAPKSignature(context, pkinfo.packageName);
Config.ConfirmationSynObj.notify();
}
}).start();
try {
Config.ConfirmationSynObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (appSignInfo == null) {
return ret;
}
}
有人知道如何锁定对象或函数以防止并发吗?
答案 0 :(得分:8)
wait
/ notify
的常见替代品是CountDownLatch
。 (也可以从java.util.concurrent
开始,但Semaphore
的反向工作 - 请参阅汤姆的答案)
您将其初始化为所需的步骤数,已完成倒计时的线程以及其他某些位置等待倒计时达到0。
void doFoo() {
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
//this is a http request
appSignInfo = getAPKSignature(context, pkinfo.packageName);
latch.countDown();
}
}).start();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (appSignInfo == null) {
return ret;
}
}
但是你在那里写的代码可以简化为
void doFoo() {
return getAPKSignature(context, pkinfo.packageName);
}
你开始第二个线程做某事,你所做的就是等待。如果在该任务运行时无事可做,请不要创建额外的线程。结果是一样的。
如果您尝试在UI线程之外执行HTTP请求,因为您获得了NetworkOnMainThreadExcpeption
,则必须采用不同的方式。虽然Android不会长时间阻止代码检测到您的代码,但它仍然存在。例如,使用AsyncTask。
答案 1 :(得分:5)
@Kayaman说得对,据我所知,如果我可以谦虚地建议:java.util.concurrent
可以节省你很多时间!
我使用的是semaphore。
来自文档:"每个acquire()都会在必要时阻止,直到获得许可证为止,然后接受它。"。
但是还有其他选择 - 我强烈建议在可能的情况下使用它,因为你应该避免像你的情况那样陷阱。
Semaphore semaphore = new Semaphore(0);
new Thread(new Runnable() {
@Override
public void run() {
//this is a http request
appSignInfo = getAPKSignature(context, pkinfo.packageName);
semaphore.release();
}
}).start();
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
答案 2 :(得分:2)
您可能正在同步块中创建并启动线程,但当线程进入Config.ConfirmationSynObj.notify();
时,您会注意到没有同步。
您需要在run()中添加一个synchronized块。
答案 3 :(得分:2)
new Thread(new Runnable() {
@Override
public void run() {
上面的帖子没有对ConfirmationSynObj
对象拥有锁定因此抛出IllegalMonitorStateException
在run
方法
@Override
public void run() {
synchronized (Config.ConfirmationSynObj) {
//this is a http request
appSignInfo = getAPKSignature(context, pkinfo.packageName);
Config.ConfirmationSynObj.notify();
}
}