我发现了Java并发的奇怪行为。请参阅下面的下一段代码:
public class Test { static CountDownLatch latch = new CountDownLatch(1); public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException { final Thread t = new MyThread(); t.start(); synchronized (t) { latch.countDown(); System.out.println("got to sleep"); t.wait(); System.out.println("wake up"); } } static class MyThread extends Thread { @Override public void run() { try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (this) { System.out.println("inside run"); // notifyAll(); } } } }
在我看来,这段代码应该挂起并永远等待,但是在控制台中的next out没有任何问题地完成了代码:
got to sleep inside run wake up
我试图找到一些关于如果线程死了通知锁的信息,但缺乏。我也没有在Java规范中找到任何信息。
但是如果我试图锁定其他对象(而不是thread对象),就会像我预期的那样工作得很好。
正如Jon Skeet所写的那样,在线程对象上同步是个坏主意,使用另一个:
public class Test {
static CountDownLatch latch = new CountDownLatch(1);
static final Object sync = new Object();
public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
final Thread t = new MyThread();
t.start();
synchronized (sync) {
latch.countDown();
System.out.println("got to sleep");
sync.wait();
System.out.println("wake up");
}
}
}
static class MyThread extends Thread {
@Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (sync) {
System.out.println("inside run");
//sync.notifyAll();
}
}
}
现在,在取消对sync.notifyAll()的注释之前,这段代码将永远不会结束;
这是因为您正在等待thread
实例。thread
在内部使用wait
/notify
/notifyall
,所以您自己也不应该这样做--您会混淆thread
,而thread
也会混淆您。特别是,当线程退出时,它调用this.notifyAll()
。
从thread.join
的文档中可以看到:
此实现使用This.wait
调用的循环,该循环以This.isalive
为条件。当线程终止时,将调用this.notifyall
方法。建议应用程序不要在thread
实例上使用wait
、notify
或notifyall
。
通常情况下,尝试锁定并等待其他任何东西都无法与之交互的对象。这样,您就可以对对象上存在的与并发相关的操作进行推理,因为它们是非常有限的。只要任意代码能够在对象上同步(并调用wait/notify等),就很难证明您的代码是正确的。这就是为什么你会经常看到这样的东西:
public class Foo {
private final Object lock = new Object();
... code which uses synchronized(lock) ...
}
问题内容: 如上面的示例,如果先进入块,则ThreadB中的后续块将告诉主线程继续。 但是我们不能保证将在)之前执行,如果ThreadB首先进入该块怎么办?会在之前执行,所以会永远挂在那里(因为不再告诉它继续执行)?通常有什么合适的方法来解决这个问题? 问题答案: 您几乎应该总是将谓词与等待/通知一起使用。也就是说,您需要可以检查的条件,例如变量变为true,队列变为空/满等。仅盲目地等待某人调用
所以我更新了代码,添加了行所做的是将主线程置于Hibernate状态一段时间,因此jvm可以获得一些时间来创建一个新线程。我正在得到我的预期输出
问题内容: 我正在尝试检查java中的wait / notify如何工作。 码: 输出返回 我期望在执行notify()时,等待将结束并被打印。但似乎只有完成打印后才能打印。 问题答案: 对象监视器锁需要执行相同锁的单个引用。 在你的榜样,你是对的一个实例,但使用从。相反,您应该使用单个通用锁定对象…例如 输出… 并可能根据线程调度更改位置。 您可以尝试将睡眠排除在障碍之外。这将释放监视器锁定,从
如果有人理解java编译器为什么这么做,请解释一下。
下面的代码是一个小示例,可以轻松重现问题。所以我有 String 类型的变量,它设置了默认值。我有3种方法: getter 塞特 将字符串转换为布尔值的方便方法 自省不会将getter作为readMethod返回,将setter作为WriteMethod返回。相反,它将isTest()方法作为readMethod返回。setter为空。 从文档中我了解到,如果类型是boolean,那么" is "
我在做Maven项目。我用log4j做了一个日志。但它在给定的文件中显示了一些starnge日志。我试图理解,为什么会出现这种奇怪的日志,但我不明白。请帮助我,为什么这些不需要的行会进入日志文件。 请帮我把这个拿开。 log.properties 我通过阅读这个链接创建了这个文件。 代码是 日志txt-(log.txt的一些起始行)