gpt4 book ai didi

java - 在非同步块(synchronized block)中等待和通知

转载 作者:行者123 更新时间:2023-12-02 00:14:56 25 4
gpt4 key购买 nike

抱歉我的格式错误。我正在使用记事本编写程序。

这是一个工作代码。我唯一的问题是,我读到通知和等待必须在同步块(synchronized block)中使用。但是,在下面的示例中,synchronized block 中没有使用 wait 和 notification,仍然没有抛出错误。

class counthrd implements Runnable {

Thread thrd;
String x;
counthrd cnt1;

counthrd() {
}
boolean suspended;
boolean stopped;

counthrd(String s, counthrd cnt1) {
thrd = new Thread(this, s);
this.cnt1 = cnt1;
thrd.start();
x = s;
}

public void run() {

try {
System.out.println("Starting " + thrd.currentThread().getName());
for (int i = 1; i < 100; i++) {
System.out.print(i + " ");
if ((i % 10) == 0) {
System.out.println();
Thread.sleep(500);
}
//synchronized(cnt1){
while (suspended) {
System.out.println("going to wait mode");
wait();
notify();
}
//}
}
} catch (Exception e) {
System.out.println(e);
}
}

synchronized void suspendme() {
suspended = true;
notify();
}

synchronized void resumeme() {
suspended = false;
notify();
}
}

class counter {

public static void main(String args[]) throws InterruptedException {
counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);
}
}

最佳答案

参见my comment 。由于 IllegalMonitorStateException 永远不会抛出,我们知道 wait 永远不会被调用。

请注意,您有两个 counthrd 实例...

counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

看看您在哪个实例上调用 suspendmeresumeme

Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);

cnt1 使用无参数构造函数进行初始化,如下所示:

counthrd() {
}

重点是 cnt1 从未真正启动自己的线程。它从来没有做任何事情,真的。 cnthrd1 是启动线程的线程,如下所示:

counthrd(String s, counthrd cnt1) {
thrd = new Thread(this, s);
this.cnt1 = cnt1;
thrd.start();
x = s;
}

需要指出的是,suspended 是一个实例字段,并且不在 cnt1cnthrd1 之间共享。修改 cnt1.suspended 不会导致 cnthrd1 进入“等待模式”。 wait 永远不会被调用,因此永远不会抛出异常。

为了演示,请尝试在 cnthrd1 上调用 suspendmeresumeme,而不是...:-)

C:\dev\scrap>javac counter.java

C:\dev\scrap>java counter
Starting thrd 1
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
going to wait mode
going to wait mode
java.lang.IllegalMonitorStateException
resuming
<小时/>

话虽这么说,我想我建议你做一些你的代码应该做的事情。

  1. 挂起声明为 volatile 。如果没有一些显式的内存排序保证,就无法保证 if cnthrd1 何时读取 suspended 的更新值。
  2. 放弃cnt1字段和实例;他们没有理由。也摆脱那个空的构造函数。
  3. Thread.currentThread 是一个静态方法;您不需要为其使用实例。除此之外,这里保证 thrd 等于 Thread.currentThread
  4. counthrd.x 等于 thrd.getName;为什么不直接使用 x 来代替呢?
  5. 使用一些更好、更具描述性的名称。例如,为什么不使用 x,而不是 name?为什么不是 thread 而不是 thrd?为什么不使用 counthrd,而不是 CountingThread
  6. 您只需要在resumeme中调用notify,而不是suspendme。 (事实上​​,如果线程正在 hibernate ,即当 (i % 10) = = 0)
  7. 您也不希望在 while(挂起) 循环中使用 notify。现在,您的 while 循环实际上也可以转换为 if 语句。
  8. 如前所述,您需要在调用 while 的代码周围进行同步(this)
  9. 避免在构造函数中执行实际逻辑,例如thrd.start()
  10. 挂起不需要同步resume 也不需要synchronized;只有 waitnotify 调用需要它。

您可以找到可以正常工作的示例的修改版本 here .

关于java - 在非同步块(synchronized block)中等待和通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12023056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com