Java多线程错误`Java.lang.IllegalMonitorStateException`

Java多线程错误`Java.lang.IllegalMonitorStateException`,java,multithreading,Java,Multithreading,我试图让两个线程相互打印出一些内容,但结果是: 0 Exception in thread "Thread-0" wait in decrement java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at thread.Multithread2.increment(Multithread2.java:38) at thread.Multithread2.run(

我试图让两个线程相互打印出一些内容,但结果是:

0
Exception in thread "Thread-0" wait in decrement
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at thread.Multithread2.increment(Multithread2.java:38)
    at thread.Multithread2.run(Multithread2.java:18)
    at java.lang.Thread.run(Unknown Source)
我已经在同步块中包含了共享对象,并在此对象上调用了wait()/notify()。我不知道为什么它仍然抛出异常

public class Multithread2 implements Runnable {

    private Integer integer;
    private int method;

    public Multithread2(Integer integer, int method) {
        this.integer = integer;
        this.method = method;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(20);
            for(int i = 0; i < 5; i++) {
                if(method == 1) {
                    increment();
                } else {
                    decrement();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void increment() throws InterruptedException {
        synchronized(integer) {
            while(integer > 0) {
                integer.wait();
            }
            System.out.println(integer);
            integer++;
            integer.notify();
        }
    }

    public void decrement() throws InterruptedException {
        synchronized(integer) {
            while(integer <= 0) {
                integer.wait();
            }
            System.out.println("decrement: " + integer);
            integer--;
            integer.notify();
        }
    }
}
相当于

integer = Integer.valueOf(integer.getValue() + 1);
因此,它使用不同的整数实例初始化整数变量。整数是不可变的,因此其状态不能更改。由于您在这个新的Integer实例上调用notify(),并且还没有获得这个新实例上的锁,因此会出现该异常

public class Multithread2 implements Runnable {

    private Integer integer;
    private int method;

    public Multithread2(Integer integer, int method) {
        this.integer = integer;
        this.method = method;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(20);
            for(int i = 0; i < 5; i++) {
                if(method == 1) {
                    increment();
                } else {
                    decrement();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void increment() throws InterruptedException {
        synchronized(integer) {
            while(integer > 0) {
                integer.wait();
            }
            System.out.println(integer);
            integer++;
            integer.notify();
        }
    }

    public void decrement() throws InterruptedException {
        synchronized(integer) {
            while(integer <= 0) {
                integer.wait();
            }
            System.out.println("decrement: " + integer);
            integer--;
            integer.notify();
        }
    }
}

使用您自己的、可变的、线程安全的计数器类。在共享的、不可变的整数实例上同步是一个糟糕的想法。顺便说一下,一个很好的经验法则是将同步的
字段设置为final
。这样做会导致编译错误,在这种情况下,编译错误是您的朋友,前提是您要注意实际告诉您的内容

相当于

integer = Integer.valueOf(integer.getValue() + 1);
因此,它使用不同的整数实例初始化整数变量。整数是不可变的,因此其状态不能更改。由于您在这个新的Integer实例上调用notify(),并且还没有获得这个新实例上的锁,因此会出现该异常

public class Multithread2 implements Runnable {

    private Integer integer;
    private int method;

    public Multithread2(Integer integer, int method) {
        this.integer = integer;
        this.method = method;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(20);
            for(int i = 0; i < 5; i++) {
                if(method == 1) {
                    increment();
                } else {
                    decrement();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void increment() throws InterruptedException {
        synchronized(integer) {
            while(integer > 0) {
                integer.wait();
            }
            System.out.println(integer);
            integer++;
            integer.notify();
        }
    }

    public void decrement() throws InterruptedException {
        synchronized(integer) {
            while(integer <= 0) {
                integer.wait();
            }
            System.out.println("decrement: " + integer);
            integer--;
            integer.notify();
        }
    }
}

使用您自己的、可变的、线程安全的计数器类。在共享的、不可变的整数实例上同步是一个糟糕的想法。顺便说一下,一个很好的经验法则是将同步的
字段设置为final
。这样做会导致编译错误,在这种情况下,编译错误是您的朋友,前提是您要注意实际对您说的话。

integer++
integer=integer+1
相同。您没有在同一个
integer
上调用
notify()
,您正在
同步
上。
integer++
integer=integer+1
相同。您不是在同一个
integer
上调用
notify()
,而是在
synchronized
上调用。或者我想您只是在
AtomicInteger
上调用。是的,您也可以使用它。“这样做会导致编译错误。”。。。在这种情况下,一个编译错误是你的朋友,只要你注意实际上是在对你说什么。@StephenC,你不要只点击IDE的“remove
final
declaration”提示,而一开始就懒得阅读错误…@StephenC谢谢,这让它更清楚了。我已经在答案中添加了您的评论,希望您不介意。或者我想您可以只使用
AtomicInteger
。是的,您也可以使用它。“这样做会导致编译错误。”。。。在这种情况下,一个编译错误是你的朋友,只要你注意实际上是在对你说什么。@StephenC,你不要只点击IDE的“remove
final
declaration”提示,而一开始就懒得阅读错误…@StephenC谢谢,这让它更清楚了。我在回答中添加了你的评论,希望你不介意。