Java的多线程NotiFyAll()唤醒线程时的顺序问题
2013-06-04 22:13
218 查看
public class ThreadPriority {
public static void main(String[] args) {
Producer p = new Producer();
p.start();
for (int i = 1; i < 5; i++) {
Consumer cr = new Consumer();
cr.setPriority(i);
cr.start();
}
}
}
class Consumer extends Thread {
public Consumer()
{
setDaemon(true);
}
public void run() {
try {
synchronized (Producer.slotNum) {
if (Producer.slotNum == 0)
Producer.slotNum.wait();
Producer.slotNum--;
System.out.println(" Thread " + this.getId() + " consumer 1!");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Producer extends Thread {
public static Integer slotNum = 10;
public Producer()
{
setDaemon(true);
}
public void run() {
synchronized (slotNum) {
slotNum++;
slotNum.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}
}
报错:Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
Thread 10 consumer 1!
at java.lang.Object.notifyAll(Native Method)
at future.Producer.run(ThreadPriority.java:51)
Thread 13 consumer 1!
Thread 11 consumer 1!
Thread 12 consumer 1!
搜了下,网上说: notifyAll()的描述,“解除那些在该对象上调用wait()方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是对象所得持有者,该方法抛出一个java.lang.IllegalMonitorStateException 异常”
这里Producer 应该是slotNum 对象的持有者吧, 必然是先通过synchronized关键字获取slotNum的锁,在通知其他等待线程吧 ,而且notifyall和wait都是在同步块内调用的,为什么还会报出这样一个异常呢?
此外写这个代码的目的就是测试下,当一群线程在wait一个对象时, notifyAll()方法唤醒线程是按照优先级的顺序呢? 还是其他?在网上搜的有两种说法,一种是按优先级,一种是说没有明确的顺序。
当然,只要是人写的程序,总是会有一定规律的吧。
由于slotNum++;改变了监视的实例,所以导致当前线程不是此对象监视器的所有者。这才是真正的原因。
由于做了自加操作,Integer 作了自动拆箱,自减完成后又自动装箱了,因此在 slotNum++之后的 slotNum 与之前的 slotNum 不是同一个对象了,所以在 notifyAll 时会抛出无效的监视器状态异常。
参考这个
http://stackoverflow.com/questions/260337/why-does-synchronized-notifyall-result-in-a-illegalmonitorstateexception
修改后的代码如下:
package future;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPriority {
public static void main(String[] args) {
for (int i = 1; i < 5; i++) {
Consumer cr = new Consumer();
cr.setPriority(i);
cr.start();
}
Producer p = new Producer();
p.start();
}
}
class Consumer extends Thread {
public Consumer()
{
setDaemon(true);
}
public void run() {
try {
synchronized (Producer.slotNum) {
if (Producer.slotNum.get()== 0)
Producer.slotNum.wait();
Producer.slotNum.decrementAndGet();
System.out.println(" Thread " + this.getId() + " consumer 1!");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Producer extends Thread {
public static AtomicInteger slotNum = new AtomicInteger(10);
public Producer()
{
setDaemon(true);
}
// public void addSlot()
// {
// slotNum ++;
// }
public void run() {
synchronized (slotNum) {
// slotNum++;
// slotNum = slotNum +1 ;
// addSlot();
slotNum.incrementAndGet();
slotNum.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}
}
public static void main(String[] args) {
Producer p = new Producer();
p.start();
for (int i = 1; i < 5; i++) {
Consumer cr = new Consumer();
cr.setPriority(i);
cr.start();
}
}
}
class Consumer extends Thread {
public Consumer()
{
setDaemon(true);
}
public void run() {
try {
synchronized (Producer.slotNum) {
if (Producer.slotNum == 0)
Producer.slotNum.wait();
Producer.slotNum--;
System.out.println(" Thread " + this.getId() + " consumer 1!");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Producer extends Thread {
public static Integer slotNum = 10;
public Producer()
{
setDaemon(true);
}
public void run() {
synchronized (slotNum) {
slotNum++;
slotNum.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}
}
报错:Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
Thread 10 consumer 1!
at java.lang.Object.notifyAll(Native Method)
at future.Producer.run(ThreadPriority.java:51)
Thread 13 consumer 1!
Thread 11 consumer 1!
Thread 12 consumer 1!
搜了下,网上说: notifyAll()的描述,“解除那些在该对象上调用wait()方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是对象所得持有者,该方法抛出一个java.lang.IllegalMonitorStateException 异常”
这里Producer 应该是slotNum 对象的持有者吧, 必然是先通过synchronized关键字获取slotNum的锁,在通知其他等待线程吧 ,而且notifyall和wait都是在同步块内调用的,为什么还会报出这样一个异常呢?
此外写这个代码的目的就是测试下,当一群线程在wait一个对象时, notifyAll()方法唤醒线程是按照优先级的顺序呢? 还是其他?在网上搜的有两种说法,一种是按优先级,一种是说没有明确的顺序。
当然,只要是人写的程序,总是会有一定规律的吧。
由于slotNum++;改变了监视的实例,所以导致当前线程不是此对象监视器的所有者。这才是真正的原因。
由于做了自加操作,Integer 作了自动拆箱,自减完成后又自动装箱了,因此在 slotNum++之后的 slotNum 与之前的 slotNum 不是同一个对象了,所以在 notifyAll 时会抛出无效的监视器状态异常。
参考这个
http://stackoverflow.com/questions/260337/why-does-synchronized-notifyall-result-in-a-illegalmonitorstateexception
修改后的代码如下:
package future;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPriority {
public static void main(String[] args) {
for (int i = 1; i < 5; i++) {
Consumer cr = new Consumer();
cr.setPriority(i);
cr.start();
}
Producer p = new Producer();
p.start();
}
}
class Consumer extends Thread {
public Consumer()
{
setDaemon(true);
}
public void run() {
try {
synchronized (Producer.slotNum) {
if (Producer.slotNum.get()== 0)
Producer.slotNum.wait();
Producer.slotNum.decrementAndGet();
System.out.println(" Thread " + this.getId() + " consumer 1!");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Producer extends Thread {
public static AtomicInteger slotNum = new AtomicInteger(10);
public Producer()
{
setDaemon(true);
}
// public void addSlot()
// {
// slotNum ++;
// }
public void run() {
synchronized (slotNum) {
// slotNum++;
// slotNum = slotNum +1 ;
// addSlot();
slotNum.incrementAndGet();
slotNum.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}
}
相关文章推荐
- java 线程上机题 循环唤醒 三个线程轮流打印 顺序 A线程->B线程->C线程
- 破除java神话之五:等待的线程是按照优先级顺序被唤醒的
- [Java多线程]ABC三个线程顺序输出的问题
- 线程的同步问题(java)
- 线程间通信(等待,唤醒)&Java中sleep()和wait()比较
- 线程间通信、等待唤醒机制、生产者消费者问题(Lock,Condition)、停止线程和守护线程、线程优先级
- Java线程(八):锁对象Lock-同步问题更完美的处理方式
- java线程安全问题之静态变量、实例变量、局部变量
- 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题
- 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题
- Java中多个线程按顺序执行
- java线程安全问题之静态变量、实例变量、局部变量
- java中的线程问题
- Java线程唤醒与阻塞
- java 中线程执行顺序控制
- Java线程:锁对象Lock-同步问题更完美的处理方式
- java中控制线程间执行顺序的方法
- Java线程(三):线程协作-生产者/消费者问题
- Java线程问题:当一个目标对象被多个线程共享时候
- Java线程唤醒与阻塞