关于Java多线程的问题,求大神解决

一个简单的例子,一个线程类代表客户,一个线程类代表厨师,
厨师每做好5个包子两个客户就吃,吃完再做。
运行时出现
java.lang.IllegalMonitorStateException错误,而且每次都只是一个人在吃。
实在是弄不明白了。。。
代码如下:
public class Resource {
//锁对象,静态资源,可以被公开访问
static Object lock = new Object();

//包子容器,静态资源,可以被公开访问
static List<String> container = new ArrayList<String>();

}

public class Producer implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized ("") {
if (Resource.container.size() == 5) {
Resource.lock.notifyAll();// 唤醒所有在等待Resource.lock这把锁的线程
} else {
System.out.println("开始制作包子");
// 模拟耗时
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Resource.container.add("包子");
}
}
}
}
}

public class Cutstom implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub

    while (true) {
        synchronized ("") {
            // 容器中没有包子了,吃货们就要等待包子
            if (Resource.container.size() == 0) {
                System.out.println("包子吃光啦,老板上包子");
                try {
                    Resource.lock.wait();// 释放自己持有了锁,并开始等待被notify
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                // 模拟耗时
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 移除吃过的包子
                System.out.println("吃货:" + Thread.currentThread().getName() + "吃包子");
                Resource.container.remove(0);
            }
        }
    }
}

}

public class Test {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Cutstom cutstom = new Cutstom() ;
    new Thread(cutstom,"a").start() ;
    new Thread(cutstom,"b").start() ;
    Producer producer = new Producer() ;
    new Thread(producer,"c").start();
}

}

console:

Exception in thread "a" 包子吃光啦,老板上包子
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at food.Cutstom.run(Cutstom.java:15)
at java.lang.Thread.run(Unknown Source)
开始制作包子
开始制作包子
开始制作包子
开始制作包子
开始制作包子
Exception in thread "c" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at food.Producer.run(Producer.java:10)
at java.lang.Thread.run(Unknown Source)
吃货:b吃包子
吃货:b吃包子
吃货:b吃包子
吃货:b吃包子
吃货:b吃包子
包子吃光啦,老板上包子
Exception in thread "b" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at food.Cutstom.run(Cutstom.java:15)
at java.lang.Thread.run(Unknown Source)

2个回答

首先你要了解这个异常为什么会抛出,这个异常会在三种情况下抛出:
1>当前线程不含有当前对象的锁资源的时候,调用obj.wait()方法;
2>当前线程不含有当前对象的锁资源的时候,调用obj.notify()方法。
3>当前线程不含有当前对象的锁资源的时候,调用obj.notifyAll()方法。
将Producer类中此位置由synchronized (“”) 改成synchronized (Resource.lock),将Cutstom类中此位置由synchronized (“”) 改成synchronized (Resource.lock) 问题解决。

javawebty
merlinlock 回复dlw840622: 线程的调用是随机的(同一个权重下),所以你没法控制吃多少,但是你可以控制轮流吃
一年多之前 回复
dlw840622
朵朵粑 非常感谢,这样确实不报错了,但出现的结果就是这5个都被a或者b吃掉,怎么才能让a和b两个线程一起吃一轮的5个呢?
一年多之前 回复

这种模型可以用BlockingQueue实现吧

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问