本帖最后由 cloudeagle_bupt 于 2013-06-05 20:40:22 编辑

解决方案 »

  1.   

    问题不在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.   


    明白了第2点问题, 应该是所谓的装箱,拆箱操作的意思吧.可是第一点说:"1 同步对象没有wait的前提情况下,已经notifyAll"
    这里Producer为什么要wait呢? 如果这时锁已经被占用,那么synchronized(){...} 是不会被执行的啊? 线程应该会自动等待吧?
      

  3.   

    你看一下你的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的方法执行,而这种操作是无任何意义的。
      

  4.   

    楼主结贴那么快啊,不知道楼主真正明白了没有,一楼说的那个锁用了Integer类型,在执行slotNum--或soltNum++的时候是改变了锁,所以达不到预期效果的,
      

  5.   

    不好意思,没有写完,点错了,所以用一个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!");
    }
    }}这样测试的效果是乱的,并没有严格按照优先级别来唤醒...