Android java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定

我将全局静态对象定义为同步锁。

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; } } 

有谁知道如何锁定对象或函数以防止并发?

wait / notify常见替代是CountDownLatch 。 (来自java.util.concurrent以及Semaphore的反向工作 – 请参阅Tom的回答)

您将其初始化为所需的步骤数,已完成倒计时的线程以及其他某些位置等待倒计时达到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。

@Kayaman说的正确,据我所知,但是如果我可能谦卑地建议: java.util.concurrent可以节省你很多时间!

我在那里使用的是一个信号量 。

从文档:“每个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(); } 

您可能正在同步块中创建并启动线程,但是当线程进入Config.ConfirmationSynObj.notify(); 你会注意到没有同步。

您需要在run()中添加一个synchronized块。

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