关于多线程的notifyall()函数求教高手 本帖最后由 cloudeagle_bupt 于 2013-06-05 20:40:22 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 问题不在Consumer 线程上面,而是在Producer线程上面问题有2个1 同步对象没有wait的前提情况下,已经notifyAll,这还不是错误的主要原因。2 看一下如下代码public void run() { synchronized (slotNum) { slotNum++; slotNum.notifyAll(); System.out.println(" Thread " + this.getId() + " producer 1!"); }}由于slotNum++;改变了监视的实例,所以导致当前线程不是此对象监视器的所有者。这才是真正的原因。对象监视器不要是逻辑变量,你可以new一个object都是可以的。 明白了第2点问题, 应该是所谓的装箱,拆箱操作的意思吧.可是第一点说:"1 同步对象没有wait的前提情况下,已经notifyAll"这里Producer为什么要wait呢? 如果这时锁已经被占用,那么synchronized(){...} 是不会被执行的啊? 线程应该会自动等待吧? 你看一下你的main函数的线程的调用顺序public static void main(String[] args) throws InterruptedException { Producer p = new Producer(); p.start(); for (int i = 1; i < 5; i++) { Consumer cr = new Consumer(); cr.setPriority(i); cr.start(); } }这里的Producer线程先创建执行,完全有可能notifyAll()先于consumer的wait的方法执行,而这种操作是无任何意义的。 楼主结贴那么快啊,不知道楼主真正明白了没有,一楼说的那个锁用了Integer类型,在执行slotNum--或soltNum++的时候是改变了锁,所以达不到预期效果的, 不好意思,没有写完,点错了,所以用一个Object类型来作为锁是可以的,第二点是,三楼的回答也是很好的,因为在启动额外线程的时候,有可能额外线程不是严格按照我们代码的编写顺序的,而且要将Producer在后面启动,即使这么做了也许达不到预期的效果,所以这里不妨在循环启动了多个Customer线程后让主线程暂停一会儿,仅仅给一个interval就可以了,第三,如果要通过这个测试notifyAll唤醒线程的优先顺序也许达不到效果的,首先priority在windows系统下并没有严格的先后顺序,所以这样测试是每一个都有可能不同,而楼主的这个程序中的Customer线程在循环启动的时候都是new出来的新的线程,在执行run方法中的同步代码块的时候并没有互相等待,所以测试达不到预期目的,这里建议用实现Runnable接口,这样就可以共同执行一个同步代码块的代码而相互等待了,经过楼主的启示:public class ThreadPriority { public static void main(String[] args) { Consumer cr = new Consumer(); for (int i = 1; i < 5; i++) { Thread thread = new Thread(cr); thread.setPriority(i); thread.start(); } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Producer p = new Producer(); p.start(); }}class Consumer implements Runnable { public void run() { try { synchronized (Producer.lock) { if (Producer.slotNum <= 10) { System.out.println("Consumer.run().if()..."); Producer.lock.wait(); } Producer.slotNum--; System.out.println(" Thread " + Thread.currentThread().getId() + "-->priority: " + Thread.currentThread().getPriority() + "consumer 1!"); } } catch (Exception e) { e.printStackTrace(); } }}class Producer extends Thread { public static final Object lock = new Object(); public static int slotNum = 10; public Producer() { setDaemon(true); } public void run() { synchronized (lock) { lock.notifyAll(); System.out.println(" Thread " + this.getId() + " producer 1!"); } }}这样测试的效果是乱的,并没有严格按照优先级别来唤醒... 正则表达式 java se 有什么用? 求助:Java中如何实现双协议(TCP、UDP)的文件传输 使用SUN 自带的那个glassfish 部署的EJB 怎么调用? java 读入、写出文件 谁来帮我看看这条程序啊? 怎样获得被JAVA调用的程序的返回值? 我用的是jdk-1_5_0_04,结果报错是:软件包 javax.servlet 不存在?在线等待! 不好意思,小弟又来麻烦大家了! 关于局部内部类实例化的问题 初学java求助 请问何谓【框架】?
问题有2个
1 同步对象没有wait的前提情况下,已经notifyAll,这还不是错误的主要原因。
2 看一下如下代码public void run() {
synchronized (slotNum) {
slotNum++;
slotNum.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}由于slotNum++;改变了监视的实例,所以导致当前线程不是此对象监视器的所有者。这才是真正的原因。
对象监视器不要是逻辑变量,你可以new一个object都是可以的。
明白了第2点问题, 应该是所谓的装箱,拆箱操作的意思吧.可是第一点说:"1 同步对象没有wait的前提情况下,已经notifyAll"
这里Producer为什么要wait呢? 如果这时锁已经被占用,那么synchronized(){...} 是不会被执行的啊? 线程应该会自动等待吧?
Producer p = new Producer();
p.start(); for (int i = 1; i < 5; i++) {
Consumer cr = new Consumer();
cr.setPriority(i);
cr.start();
}
}这里的Producer线程先创建执行,完全有可能notifyAll()先于consumer的wait的方法执行,而这种操作是无任何意义的。
public static void main(String[] args) { Consumer cr = new Consumer();
for (int i = 1; i < 5; i++) {
Thread thread = new Thread(cr);
thread.setPriority(i);
thread.start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Producer p = new Producer();
p.start();
}
}class Consumer implements Runnable {
public void run() {
try {
synchronized (Producer.lock) {
if (Producer.slotNum <= 10) {
System.out.println("Consumer.run().if()...");
Producer.lock.wait();
}
Producer.slotNum--;
System.out.println(" Thread " + Thread.currentThread().getId()
+ "-->priority: "
+ Thread.currentThread().getPriority() + "consumer 1!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Producer extends Thread {
public static final Object lock = new Object();
public static int slotNum = 10;
public Producer() {
setDaemon(true);
}
public void run() {
synchronized (lock) {
lock.notifyAll();
System.out.println(" Thread " + this.getId() + " producer 1!");
}
}}这样测试的效果是乱的,并没有严格按照优先级别来唤醒...