JAVA 多线程 IllegalMonitorStateException 异常原因及解决办法

本文深入探讨了Java中线程通信的重要概念,包括wait(), notify()和notifyAll()方法的正确使用方式,以及如何在同步控制块内进行调用以避免IllegalMonitorStateException异常。通过一个生产者消费者模式的实例,展示了如何利用这些方法实现线程间的有效通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在同步控制方法或同步控制块里调用wait()notify()notifyAll()。如果在非同步控制方法里调用这些方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常,并伴随着一些含糊的消息,比如"当前线程不是拥有者"。消息的意思是,调用wait()notify()notifyAll()的线程在调用这些方法前必须"拥有"对象的锁。当前的线程不是此对象锁的所有者,却调用该对象的notify()notify()wait()方法时抛出该异常。

  wait/notfiy 一定要在同步代码块里,并且持有相同的对象锁;

package com.xiaoye;

/**
 * @Description :
 * @Author : ChenYao
 * @Version : 1.0
 * @Create : 2019/6/8  23:15
 * @Update : 2019/6/8  23:15
 * @see :
 */
public class ThreadProviderConsumerDemo {
    public static void main(String[] args) {
        Person person = new Person();
        //false生產;true消费;
        person.flag = false;
        Provider provider = new Provider(person);
        Consumer consumer = new Consumer(person);
        provider.start();
        consumer.start();
    }
}

class Provider extends Thread {
    Person person;

    public Provider(Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (person) {
                if (person.flag) {
                    try {
                        person.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (count == 0) {
                    person.name = "小花";
                    person.sex = "女";
                } else {
                    person.name = "小明";
                    person.sex = "男";
                }
                count = (count + 1) % 2;
                person.flag = true;
                person.notify();
            }
        }
    }
}

class Consumer extends Thread {
    Person person;

    public Consumer(Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (person) {
                if (person.flag) {
                    System.out.println(person);
                    person.flag = false;
                    person.notify();
                }
                try {
                    person.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Person {
    public String name;
    public String sex;
    public boolean flag;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer();
        return stringBuffer
                .append("Person:[name=")
                .append(name)
                .append(",sex=")
                .append(sex + ",flag=" + flag + "]")
                .toString();
    }
}

Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值