【问题标题】:How can i change the state of thread which is getting accessed in another monitor如何更改在另一个监视器中访问的线程的状态
【发布时间】:2013-07-10 14:36:46
【问题描述】:

我正在实现一个控制器类,它必须在处理相同类型数据的线程上应用锁。因此,在这种情况下,我构建了两个用于应用和释放锁的类。

现在我在重新锁定时收到 IllegalMonitorStateException 异常。 我知道目前我在另一个线程的监视器中。

这是锁定机制:

ConcurrentHashMap<String, Thread> Map = new ConcurrentHashMap<String, Thread>();
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    final Object lock = new Object();
    for (Thread thread : threadSet) {
        StringBuffer sb = new StringBuffer(thread.getName().toString());
        if ((sb.length() == 22) && (sb.toString().matches("[0-9]+"))
                && (thread != Thread.currentThread())) {
            utiMap.put(thread.getName().toString(), thread);
        }
    }

    synchronized (lock) {
        if (utiMap.containsKey(key)) {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                lock.notifyAll();
            }
        } 
    }

以下是锁释放逻辑。

ConcurrentHashMap<String, Thread> Map = new ConcurrentHashMap<String, Thread>();
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    Object lock = new Object();
    for (Thread thread : threadSet) {
        StringBuffer sb = new StringBuffer(thread.getName().toString());
        if ((sb.length() == 22) && (sb.toString().matches("[0-9]+"))
                && (thread != Thread.currentThread()) && thread.getState().name().equals("WAITING")) {
            utiMap.put(thread.getName().toString(), thread);
            System.out.println("I am in controller Release -- ");
            thread.resume();
        }
    }

【问题讨论】:

  • 我没有看到任何锁定。被锁定的对象只能在任何地方创建和使用。你有更完整的例子吗?
  • 不要用StringBuffer,十几年前就被StringBuilder代替了。
  • @BITSSANDESH 所以向我们展示有问题的代码,而不是有效的代码。顺便说一句 resume() 已弃用,只能在您不应该使用的挂起()线程上使用。
  • 目前尚不清楚您要实现什么目标或为什么要这样做,但是您的代码存在很多问题,我不确定您是否应该尝试这样做。这是 Oracle 专家说你不应该尝试的那种事情,除非你真的、真的知道自己在做什么,否则这可能是一个非常糟糕的主意。
  • 好的,在 Java 中已经有许多信号/消息传递/工作传递方法以及许多也执行此操作的第三方库中,您认为最相似的是什么以及您需要它如何不一样?

标签: java multithreading jvm


【解决方案1】:

您的代码……恐怕……完全错误。

但更糟糕的是,我怀疑您正在尝试做一些无法完成的事情。或者如果可以,那么不应该这样做,因为它无法安全地进行


您似乎正试图让一个线程导致另一个线程停止运行一段时间......然后恢复。您正在尝试在没有受控线程的合作/参与的情况下执行此操作。 (对于“必须在线程上应用锁定” ...以及您的代码正在执行的旋转,这是我能想到的唯一解释。)

不幸的是,您不能在 Java 中安全地做到这一点。如果你打算这样做,你需要在一个线程对象上调用thread.suspend() 来暂时停止它,然后在同一个线程对象上调用thread.resume() 让它继续。但这两种方法在很久以前就弃用了,因为(显然)它们容易死锁。


还有几点需要注意:

final Object lock = new Object();
...
synchronized(lock) { ....

那个代码是错误的。 Java 原始锁通过在一个(共享)对象上拥有多个线程synchronize 来工作。但是您正在同步当前线程可以看到的锁实例。最终结果将是实际上没有同步,也没有锁定。

lock.wait();

这等待某个其他线程到notify 那个lock 对象,但是...

  • 没有其他线程可以看到该lock 对象,并且
  • 另一个调用lock.notify 的地方是在当前线程上……在你因中断而醒来之后。 (但如果线程已经被唤醒,则通知事件将被简单地丢弃。)

建议:

  1. 不要尝试这样暂停/恢复线程。如果您希望某个线程被“控制”,那么修改该线程以定期检查它是否应该暂停。

  2. 您真的非常需要阅读 Java 并发,因为您尝试的解决方案是......坦率地说......垃圾。

【讨论】:

  • 这对我来说也很奇怪。 Thasnk 对我的解决方案进行了很好的解释。我正在解决问题,我会改变设计。
猜你喜欢
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 2019-01-08
  • 2021-07-30
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 2022-11-21
相关资源
最近更新 更多