Java 使用2个不同线程打印奇偶数时出现非法监视异常
下面是我使用两个不同线程打印奇偶数的代码。 但是在运行代码时,我得到了非法的monitorexception 请帮助我理解为什么我会得到这个例外Java 使用2个不同线程打印奇偶数时出现非法监视异常,java,multithreading,Java,Multithreading,下面是我使用两个不同线程打印奇偶数的代码。 但是在运行代码时,我得到了非法的monitorexception 请帮助我理解为什么我会得到这个例外 class PrintOddEven { public static void main(String args[]) { Integer num = new Integer(1); Thread odd = new Thread(new Odd(num)); Thread even = new
class PrintOddEven {
public static void main(String args[]) {
Integer num = new Integer(1);
Thread odd = new Thread(new Odd(num));
Thread even = new Thread(new Even(num));
odd.start();
even.start();
}
}
class Odd implements Runnable {
Integer num;
public Odd(Integer num) {
super();
this.num = num;
}
@Override
public void run() {
while (num <= 100) {
try {
synchronized (num) {
if (num % 2 == 0) {
num.wait();
}
System.out.println(num);
num++;
num.notifyAll();
num.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Even implements Runnable {
Integer num;
public Even(Integer num) {
super();
this.num = num;
}
@Override
public void run() {
while (num <= 100) {
try {
synchronized (num) {
if (num % 2 != 0) {
num.wait();
}
System.out.println(num);
num++;
num.notifyAll();
num.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class-printodd偶数{
公共静态void main(字符串参数[]){
整数num=新整数(1);
线程奇数=新线程(新奇数(num));
线程偶数=新线程(新偶数(num));
奇。开始();
偶数。开始();
}
}
类奇数实现可运行{
整数数;
公共奇数(整数){
超级();
this.num=num;
}
@凌驾
公开募捐{
while(num
如果你执行这段代码,你会发现hashcode
是不同的(这是它们的值,即1和2),那么如果hashcode
是不同的,那么它怎么可能是同一个对象(正如@Nathan Hughes所指出的那样)。这就是你得到java.lang.IllegalMonitorStateException
import java.util.concurrent.atomic.AtomicInteger;
class PrintOddEven {
public static void main(String args[]) {
AtomicInteger num = new AtomicInteger(1);
Thread odd = new Thread(new Odd(num));
Thread even = new Thread(new Even(num));
odd.start();
even.start();
}
}
class Odd implements Runnable {
AtomicInteger num;
public Odd(AtomicInteger num) {
super();
this.num = num;
}
@Override
public void run() {
while (num.get() < 100) {
try {
synchronized (num) {
if (num.get() % 2 == 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Even implements Runnable {
AtomicInteger num;
public Even(AtomicInteger num) {
super();
this.num = num;
}
@Override
public void run() {
while (num.get() <= 100) {
try {
synchronized (num) {
if (num.get() % 2 != 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
导入java.util.concurrent.AtomicInteger;
类打印奇偶{
公共静态void main(字符串参数[]){
AtomicInteger num=新的AtomicInteger(1);
线程奇数=新线程(新奇数(num));
线程偶数=新线程(新偶数(num));
奇。开始();
偶数。开始();
}
}
类奇数实现可运行{
原子整数;
公共奇数(原子整数){
超级();
this.num=num;
}
@凌驾
公开募捐{
while(num.get()<100){
试一试{
已同步(num){
如果(num.get()%2==0){
num.wait();
}
系统输出打印项数(num);
num.getAndIncrement();
num.notifyAll();
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
类甚至实现了可运行的{
原子整数;
公共偶数(原子整数){
超级();
this.num=num;
}
@凌驾
公开募捐{
while(num.get())整数对象是不可变的。当您更改其值时,您将用新实例替换变量引用的对象。线程获取num引用的对象上的锁,然后递增该数字,从而用另一个对象替换该对象。然后线程对num引用的对象调用notifyAll,这与它获取锁的对象不同。你不允许这样做,这就是非法监视器状态异常告诉你的
TLDR:锁不在变量上,而是在对象上。增加不可变对象的值会将该对象换成另一个对象,其中没有任何对象获得锁
使用一个不用于任何其他用途的专用锁,并将其传递给奇数和偶数对象。除非您解释为什么这会产生差异,否则此答案没有用处。
import java.util.concurrent.atomic.AtomicInteger;
class PrintOddEven {
public static void main(String args[]) {
AtomicInteger num = new AtomicInteger(1);
Thread odd = new Thread(new Odd(num));
Thread even = new Thread(new Even(num));
odd.start();
even.start();
}
}
class Odd implements Runnable {
AtomicInteger num;
public Odd(AtomicInteger num) {
super();
this.num = num;
}
@Override
public void run() {
while (num.get() < 100) {
try {
synchronized (num) {
if (num.get() % 2 == 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Even implements Runnable {
AtomicInteger num;
public Even(AtomicInteger num) {
super();
this.num = num;
}
@Override
public void run() {
while (num.get() <= 100) {
try {
synchronized (num) {
if (num.get() % 2 != 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}