Java错误:线程“main”中出现异常java.lang.IllegalMonitorStateException:当前线程不是所有者

tv6aics1  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(171)

我试图在java中使用线程进行等待,但我得到了错误:Exception in thread "main" java.lang.IllegalMonitorStateException: current thread is not owner
我试过了

Thread t = new Thread();
try {
    t.wait(2000);
} catch (InterruptedException e) {
    //TODO Auto-generated catch block
    e.printStackTrace();
}

但它没有工作,我搜索了StackOverFlow的答案,但我找不到任何有用的东西

qyyhg6bp

qyyhg6bp1#

wait是一个低级构造,旨在等待某些事情发生,并且该事情主要是“x时间已经过去”。这是给一些 * 其他 * 线程的信号:这一刻...醒醒!
如果您只想让线程等待指定的时间,那么您要查找的调用不是t.wait,而是Thread.sleep(1000)-它睡眠1秒(1000毫秒)。
waitnotify/notifyAll一起使用(这两种方法几乎做同样的事情)。一个线程等待,另一个线程调用notify,这会导致第一个线程被唤醒。是的,有一个wait的重载变体,它需要几毫秒的时间;该变量将等待,直到指定的时间量已经过去或通知被调用;以较早发生者为准。
要使用wait/notify,你需要一个对象(并且 * 所有 * 对象都可以做到这一点;回想起来,这不是设计Java语言这一部分的好方法,但它就是这样;现在改变它将是非常向后不兼容的)-你需要一个对象,因为你的代码的不同部分可以选择同时做这个等待/通知的事情,如果他们都搞不清谁在向谁发出信号,那就不行了。
此外,“我等待直到你告诉我恢复”的概念往往会很快遇到一些非常严重的线程错误,所以在实践中,因为这样的信号无论如何都需要某种CPU门控,java要求在等待或通知之前,您拥有该对象上的监视器。综合起来,这就是它看起来的样子:

public class TrainStationPlatform {
  private final Object lock = new Object();
  private Train atPlatform = null;

  public void enterStation(Train train) {
    synchronized (lock) {
      while (atPlatform != null) {
        // Oh no! There's a train already at the platform!
        lock.wait(); // let's wait for it to leave.
      }

      // The platform is clear, we can enter!
      atPlatform = train;
    }
  }

  public void leave() {
    synchronized (lock) {
      if (atPlatform == null) throw new IllegalStateException("No train");
      atPlatform = null;
      lock.notifyAll();
    }
  }
}

这显示了如何使用它:

  • 上面的代码是'safe':当使用此代码时,2列列车不可能同时在站台上。为了理解这段代码,假设每个train都是它自己的线程,并且自己调用enter(this)leave()。当站台上已经有另一列火车时,任何试图进入站台的火车都将“冻结”(它的enter调用将暂停,直到已经在那里的火车起飞,然后它将进入站台,enter方法返回)。

  • 你不能调用x.notifyx.wait,除非你在一个synchronized (x)块中,其中所有的x-es都引用同一个对象。

  • 顺便说一句,锁定公共可见的东西是一个非常糟糕的主意(也许其他代码也锁定了它,那么你的代码就是一个没有人能理解或正确测试的错误的意大利面条!). threads是非常公开的,事实上,线程一直在锁定自己,所以把它们作为锁对象是很可怕的。

  • 合并以上两条规则,您可以正确地得出结论,调用t.wait()(其中t是一个线程)永远不是正确的操作。不要这样做。**

  • 它显示了 * 为什么 * 需要锁定(synchronized)。假设同步的东西不在那里-你会得出结论,有一列火车,在得出这个结论和调用wait()之间,假设另一个线程让那里的火车离开。你仍然在调用wait,等待一个永远不会发生的事件(因为火车已经开走了)。这是一种疯狂的技巧,这种构造完全避免了 * 要求 * 你锁定你想首先调用wait on的think。上面的代码永远不会遇到这个问题。

  • 当你调用x.wait()时,xsynchronized块,冻结所有其他想要进入这样一个同步结构的线程)上的锁被放弃-其他线程现在可以进入。

  • 当你的wait调用返回时(如果你使用了超时,或者因为有人调用了notify),你的线程不会立即继续。毕竟,调用notify需要有锁,wait()在重新获取锁之前不会继续,这意味着它必须等待调用notify的对象首先到达其synchronized块的末尾。

  • notify()唤醒一个随机的wait() ing线程,notifyAll()唤醒所有线程。更明智的做法是执行检查,以确认循环中是否存在您需要的任何内容(或者不存在,需要wait() ing for),并使用notifyAll()。更容易推理,并且没有有意义的性能差异。

  • 这些都是相当低级的;通常在java.util.concurrent包中有一些更容易使用的东西,并且对于您所需要的任何线程间信令都更有意义。

  • 如果你不需要在线程之间进行信号/门控,就不要使用这个东西。使用Thread.sleep代替。

  • 无论你用什么对象作为锁,实际上都应该是private--你需要非常小心地跟踪谁把它用作锁,如果你直接控制之外的代码可以看到这个对象,你就不能这样做了。如果你公开它,你要么添加大量的文档,精确地解释任何获取此对象的代码可以做什么,不能做什么,以及应该如何使用它,或者你的代码是一个错误的混乱,迟早会导致非常讨厌的间歇性heisenbugs,需要几个月的时间来修复或最终无法修复。那就不要

  • 当您在synchronized (x)块中 not 时调用x.waitx.notify/notifyAll时,会发生异常java.lang.IllegalMonitorStateException: current thread is not owner

  • 如果希望对象是可序列化的,请使用private Object lock = new Object[0]。数组是可序列化的; new Object()不是,new Object[0]和它们来的时候一样重量轻。

vpfxa7rd

vpfxa7rd2#

您创建的线程从未启动。我觉得你应该这样做:

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            this.wait(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
});

t.start();

相关问题