我这里有两个类,实现了两个线程,代码程序见下面class ThreadA {
/**
 * @param args
 */
/**
 * @param args
 */
public static void main(String[] args) {
Thread b = new Thread(new ThreadC());
//ThreadC b = new ThreadC();
b.start();

System.out.println("b is start....");
synchronized (b)// 括号里的b是什么意思,起什么作用?
{
try {
//Thread.sleep(20);
//b.setTotal();
System.out.println("Waiting for b to complete...");
b.wait();// 这一句是什么意思,究竟让谁wait?
System.out.println("Completed.Now back to main thread");
} catch (InterruptedException e) {
}
}
}
}
public class ThreadC implements Runnable {
public int total;
public void setTotal(){
total++;
}

public void run(){
synchronized (this) { System.out.println("ThreadC is running..");
/*try{
Thread.sleep(1000);
}catch(InterruptedException e){}*/
for (int i = 0; i < 20; i++) {
total += i;
System.out.println("total is " + total);
}
notify();
}
}}
这里执行mian方法已经打印的东西,
b is start....
ThreadC is running..
Waiting for b to complete...
total is 0
total is 1
total is 3
total is 6
total is 10
total is 15
total is 21
total is 28
total is 36
total is 45
total is 55
total is 66
total is 78
total is 91
total is 105
total is 120
total is 136
total is 153
total is 171
total is 190
Completed.Now back to main thread
我这里有一个郁闷的事情,就是从打印ThreadC is running..的时候,那可以看的出来已经进入C线程,而且此时线程拥有此对象的锁(JAVA规定任何时候只有一个线程拥有此对象的锁),但是接着怎么又会打印Waiting for b to complete...呢,这里不是提示A线程也进入这个对象锁了,因为synchronized这个关键字可以获得锁,这样看来不是两个线程同时获得了同一个对象的锁但是我把public class ThreadC implements Runnable {改成public class ThreadC extends Thread {这个,把Thread b = new Thread(new ThreadC());改成ThreadC b = new ThreadC();,则打印
b is start....
ThreadC is running..
total is 0
total is 1
total is 3
total is 6
total is 10
total is 15
total is 21
total is 28
total is 36
total is 45
total is 55
total is 66
total is 78
total is 91
total is 105
total is 120
total is 136
total is 153
total is 171
total is 190
Waiting for b to complete...
Completed.Now back to main thread在这里打印我认为是正确的,运用了同一个锁,
忘高手指教了,还是我理解有错误,谢谢,我都郁闷了好几天了,一直想不通

解决方案 »

  1.   


    class ThreadA {
    /**
    * @param args
    */
    /**
    * @param args
    */
    public static void main(String[] args) {
    Thread b = new Thread(new ThreadC());
    //ThreadC b = new ThreadC();
    b.start();System.out.println("b is start....");
    synchronized (b)// 括号里的b是什么意思,起什么作用?
    {
    try {
    //Thread.sleep(20);
    //b.setTotal();
    System.out.println("Waiting for b to complete...");
    b.wait();// 这一句是什么意思,究竟让谁wait?
    System.out.println("Completed.Now back to main thread");
    } catch (InterruptedException e) {
    }
    }
    }
    }
    public class ThreadC implements Runnable {
    public int total;
    public void setTotal(){
    total++;
    }public void run(){
    synchronized (this) {System.out.println("ThreadC is running..");
    /*try{
    Thread.sleep(1000);
    }catch(InterruptedException e){}*/
    for (int i = 0; i < 20; i++) {
    total += i;
    System.out.println("total is " + total);
    }
    notify();
    }
    }}
      

  2.   

    b是线程ThreadC的一个实例,wait()是等notify()结束
      

  3.   

    http://www.it.com.cn/f/edu/0511/26/203713.htm希望对你有帮助
      

  4.   

    楼主第一个程序,整个程序中只有b和main两个线程,c不是线程吧看了半天,好多不了解的地方:
    1、main线程和b线程锁的到底分别是什么,如果都是b,为什么一个没执行完另外一个就能拿到锁,如果不是b,为什么b线程中最后的notify方法可以唤醒b.2、b线程为什么执行了一半,刚打印完就一定会跳回main线程,里面没有用wait或者sleep啊....
    而且还有隐患,如果mian线程没有先执行synchronized (b)里面的wait内容,而是b线程先执行完notify(),mian线程就会一直卡死着wait下去
      

  5.   

    我也不理解啊。
    Thread b = new Thread(new ThreadC());
    这里的b和new ThreadC()应该是不同的对象啊,怎么调用new ThreadC()里的notify会通知到b呢?
      

  6.   

    改了一下代码
    notify(); -->this.notify();
    就不会通知到主线程了。
    这两者还有区别!!!
      

  7.   

    很明显嘛
    ThreadC.run里的 synchronized (this) 锁定的是ThreadC类的对象
    而main里的b是一个Thread对象
    显然锁定了不同的对象,自然得不到你想要的结果main里前3行改为如下代码ThreadC b = new ThreadC();
    Thread thread = new Thread(b);
    thread.start();
      

  8.   


    但是如果锁住的不是同一个对象,那为什么notify()能够唤醒主线程
      

  9.   

    你看结果了吗?锁的是不同的对象,为什么调用notify能唤醒主线程?
      

  10.   

    其实就算你不执行notify
    主线程也可以被唤醒
      

  11.   

    这个应该是和Java里的线程模型有关
    线程b是在主线程里生成并启动的,那么线程b就是主线程的子线程
    在Java里必须某个线程的所有子线程都执行完毕,该线程才可以结束估计在底层实现里,每个线程会记录其子线程的状态。当该线程执行完毕时,会等待其所有子线程执行完毕才结束。那么线程如何获取所有子线程已执行完毕呢?子线程结束前,执行notify通知自己的父线程也就是说,上面线程里的 notify调用是多余的
      

  12.   

    查看JDK的Thread源码
    找到函数定义
    private native void stop0(Object o);
    这个函数在线程终结前调用
    估计里面会执行类似于如下的代码
    //等待所有子线程结束
    for(Thread th:childThreads)
       th.join();
    //通知父线程
    syn..(this)
      notify();
    也就是说,在ThreadC的run函数执行完后,会调用所在线程对象的notify函数,即b.notify()
    就让主线程里的wait等待解除了
      

  13.   


    这个解释有点牵强啊。那你怎么解释改了一下代码
    notify(); -->this.notify();
    主线程就不会触发了呢?
      

  14.   

    这个应该是如上面7楼所说,构成死锁了吧
    应该不会总是出现的。
    反正我这里把notify注释掉,一样执行到底
      

  15.   

    另外
    notify()和this.notify()有区别么?
      

  16.   


    package cn.leisore.daily._2010_06_03;public class ThreadMain {
        public static void main(String[] args) {
            
            final Thread t =   new Thread(){
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    }
            };
            t.start();        new Thread(){
                public void run() {
                    synchronized (t)
                    {
                        try {
                            t.wait();
                            System.out.println("t1");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            new Thread(){
                public void run() {
                    synchronized (t)
                    {
                        try {
                            t.wait();
                            System.out.println("t2");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }输出:
    t2
    t1感觉这是一个特例。
    即当一个线程实例变量运行结束之后
    jvm会notify所有的wait此实例变量的方法??
      

  17.   

    class ThreadA {
        /**
        * @param args
        */
        /**
        * @param args
        */
        public static void main(String[] args) {
            Thread b = new Thread(new ThreadA());
            //ThreadA b = new ThreadA();
            b.start();
            Object obj = new Object();
            System.out.println("b is start....");        Thread c = new Thread();
            c.start();
            synchronized (c)// 括号里的b是什么意思,起什么作用?
            {
                try {
                //Thread.sleep(20);
                //b.setTotal();
                    System.out.println("Waiting for b to complete...");
                    c.wait();// 这一句是什么意思,究竟让谁wait?
                    System.out.println("Completed.Now back to main thread");
                } catch (InterruptedException e) {
                }
            }
        }
    }
    public class ThreadA implements Runnable {
        public int total;
        
        
        public void setTotal(){
            total++;
        }
        
        public void run(){
            synchronized (this) {
                
                System.out.println("ThreadA is running..");
                /*try{
                Thread.sleep(1000);
                }catch(InterruptedException e){}*/
                for (int i = 0; i < 20; i++) {
                    total += i;
                    System.out.println("total is " + total);
                }
                notify();
            }
        }}
      

  18.   

    我运行结果notify()和this.notify()都一样
      

  19.   

    我错了估计是主线程在wait之前,子线程已经notify了
    这个好像就点道理,有什么理论依据吗?
      

  20.   

    当然这个notify加与不加一个样
      

  21.   


    public class ThreadA {
        /**
         * @param args
         */
        /**
         * @param args
         */
        public static void main(String[] args) {
            Thread b = new Thread(new ThreadC());// 注意这里有两个对象,一个是Thread类型的b,一个是ThreadC类型的匿名对象。
            // ThreadC b = new ThreadC();
            b.start();        System.out.println("b is start....");
            synchronized (b)// 这里是一个b的同步块(不明白就百度一下)
            {
                try {
                    // Thread.sleep(20);
                    // b.setTotal();
                    System.out.println("Waiting for b to complete...");
                    b.wait();// 让获得b对象锁的当前线程wait,在这里即本线程。
                    System.out.println("Completed.Now back to main thread");
                } catch (InterruptedException e) {
                }
            }
        }
    }class ThreadC implements Runnable {
        public int total;    public void setTotal() {
            total++;
        }    public void run() {
            synchronized (this) {// 这个同步块加到上面提到的匿名对象上了,并没有加到外围的b上面。这就是为什么LZ觉得两个线程同时获得了同一个对象的锁(其实是不同的两个对象,所以两个线程能够同时进入)。            System.out.println("ThreadC is running..");
                /*
                 * try{ Thread.sleep(1000); }catch(InterruptedException e){}
                 */
                for (int i = 0; i < 20; i++) {
                    total += i;
                    System.out.println("total is " + total);
                }
                notify();
            }
        }}这就很明显了,当ThreadC implements Runnable的时候,两个同步块分别加到Thread类型对象和ThreadC类型对象,这是两个不同的对象,所以两个线程能够分别同时进入这两个同步块。
    而把ThreadC修改为继承Thread类之后,两个同步块加在了同一个对象上,结果就可想而知了吧。
      

  22.   


     那为什么ThreadC后面的notify(),存在不存在可以回到主线程啊,麻烦能否说下JAVA的线程模型啊
      

  23.   

    我就想知道谁能解释下这个地方:System.out.println("ThreadC is running..");-----这里,为什么b线程打印完后就调回主线程而不是继续执行!!-------
    for (int i = 0; i < 20; i++) {
    total += i;
    System.out.println("total is " + total);
    }