java - 如何更改在另一个监视器中访问的线程的状态

标签 java multithreading jvm

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

现在我在真正锁定时收到 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();
        }
    }

最佳答案

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

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


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

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


还有一些需要注意的事项:

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

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

lock.wait();

这会等待其他线程通知锁定对象,但是...

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

建议:

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

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

关于java - 如何更改在另一个监视器中访问的线程的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17573528/

相关文章:

java - Android 内容提供者修改/创建日期

java - Hadoop:堆空间和gc问题

python - 这个 while 循环是如何退出的?

java - 了解HotSpot中的notify方法

JAVA_HOME 路径适用于 Java,但不适用于 Android Studio

java - 当我在 java 执行代码中设置断点时,它到底做了什么?

java - 将 Java 日期时间与当前时间进行比较

c++ - 更多线程,更好的性能?

java.lang.IllegalStateException : Failed to start new transaction (current thread already has a transaction

java - 如何在 Spring Boot 中选择理想的分页方式?