gpt4 book ai didi

java等待并通知

转载 作者:行者123 更新时间:2023-11-30 02:58:30 25 4
gpt4 key购买 nike

我正在使用一个整数变量并与两个线程共享。一个线程应该依次打印偶数,一个线程应该打印奇数。但notify()抛出IllegalMonitorStateException。

package mywaitnotifytest;
public class App {

public static void main(String[] args) {
Integer i=0;
Even even = new Even(i);
even.setName("EvenThread");
Odd odd = new Odd(i);
odd.setName("OddThread");
even.start();
odd.start();
}
}

class Even extends Thread{

Integer var;

Even(Integer var){
this.var=var;
}

@Override
public void run() {
while(true){
synchronized (var) {
if(var%2==0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}

}
}

class Odd extends Thread{

Integer var;

Odd(Integer var){
this.var=var;
}

@Override
public void run() {
while(true){
synchronized (var) {
if(var%2!=0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}
}
}

输出是:

奇数线程 1

Exception in thread "OddThread" java.lang.IllegalMonitorStateException

at java.lang.Object.notify(Native Method)

at mywaitnotifytest.Odd.run(App.java:67)

最佳答案

我认为这与给出另一个答案的通常答案有很大不同。

在本例中,您使用的是同步。当您应用锁时,它是在对象上而不是引用上。

<小时/>
synchronized (var) {

这会锁定对象 var 引用,而不是将 var 作为字段锁定。

<小时/>
var++;

这会替换 var 指向的对象。与此相同

var = Integer.valueOf(var.intValue() + 1);

注意:Integer 实际上所有原始包装器都是不可变的。当您对它们执行任何操作时,您实际上是在拆箱、使用原始值进行计算并重新装箱对象。如果被池化,则可以取回相同的对象。例如

Integer i = 10;
i += 0; // gives back the same object.

但是,如果对象没有被池化

Double d = 10;
d += 0; // creates a new object.
<小时/>
var.notify();

尝试对新对象(而不是已锁定的对象)调用notify

<小时/>

您不应该尝试锁定您变异的字段。它不会做它看起来做的事情。您也不应该锁定池对象。在这种情况下,您可以让另一个线程使用相同的 Integer 来实现不相关的目的,并且 notify() 将唤醒一个不相关的线程。

要正确使用等待/通知,您应该

  • notify()notifyAll() 在另一个共享字段中发生状态更改后。
  • 您应该使用 while 循环进行 wait() 来检查状态更改。

如果你不这样做

  • 如果另一个线程没有等待,notify 可能会丢失。
  • 即使没有调用任何通知,wait 也可能会被虚假唤醒。

For the above requirement what is the edit suggested in the code? How do i share the same object for multiple threads?

public class PingPong implements Runnable {    
static class Shared { int num; }

private final Shared var;
private final int bit;

public static void main(String[] args) {
Shared var = new Shared();
new Thread(new PingPong(var, 0), "EvenThread").start();
new Thread(new PingPong(var, 1), "OddThread").start();
}

PingPong(Shared var, int bit) {
this.var = var;
this.bit = bit;
}

@Override
public void run() {
try {
String name = Thread.currentThread().getName();
while (true) {
synchronized (var) {
while (var.num % 2 == bit)
var.wait();

var.num++;
System.out.println(name + " " + var.num);
var.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}

关于java等待并通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36566571/

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