程序代码如下:
import java.lang.Runnable;
import java.lang.Thread;public class DemoThread implements Runnable {

public DemoThread() {
TestThread testthread1 = new TestThread(this, "1");
TestThread testthread2 = new TestThread(this, "2");

testthread2.start();
testthread1.start();

}

public static void main(String[] args) {
DemoThread demoThread1 = new DemoThread();

}

public void run() {

TestThread t = (TestThread) Thread.currentThread();
try {
if (!t.getName().equalsIgnoreCase("1")) {
synchronized (this) {
wait();
}
}
while (true) {

System.out.println("@time in thread" + t.getName() + "="+ t.increaseTime());

if (t.getTime() % 10 == 0) {
synchronized (this) {
           System.out.println ("****************************************");
notify();
if (t.getTime() == 100) {

break;
}
wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

}class TestThread extends Thread {
private int time = 0;

public TestThread(Runnable r, String name) {
super(r, name);
}

public int getTime() {
return time;
}

public int increaseTime() {
return ++time;
}

}
代码中两次用到了wait,一次用到了notiy,请问他们的作用分别是如何来控制线程的呢

解决方案 »

  1.   

    一个用于synchronized语句中的对象称为一个监视器,当一个线程获得了synchronized(object)语句中的
    代码块的执行权,就意味着它锁定了监视器。在一个时间内,只能有一个线程可以锁定监视器。所以其他的线
    程在试图进入监视器前都将被挂起,直到锁定了监视器的线程执行完毕,监视器被解锁。并且一个刚锁定了
    监视器的线程被解锁后,可以马上再次进入并锁定同一监视器。有了监视器的概念,再来看看下面几个方法
    的含义:
    wait:告诉当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify为止。
    notify:唤醒同一对象监视器中调用wait的第一个线程。用于类似饭馆有一个空位后通知所有等候就餐
    的顾客中的第一位可以入坐的情况。
    notifyAll:唤醒同一对象监视器中调用wait的所有线程,具有最高优先级别的线程首先被唤醒并执行。
    用于某个不定期的培训班终于招生满额后,通知所有学员来上课的情况,先到达的,会先安排住宿。
      

  2.   

    这是多线程交互的问题:wait调用的时候肯定要在synchronize中,因为wait的时候必须已经拥有lock,但是wait调用之后就释放lock,直到notify或者notifyAll调用的时候重新进入运行队列中。notifyAll就是从等待队列中随机找一个线程开始运行!
      

  3.   

    在一个DemoThread对象中启动了两个线程test1和test2,test1在刚进入run的时候就会开始等待,在这里真正发生的事情是test1进入了DemoThread对象的等待区,在JAVA中任何一个对象都有自己的等待区(这也是为什么wait(),notify()和notifyAll()是Object类的方法而不是Thread类的方法的原因)。这里的wait()相当与this.wait(),效果和demoThread1.wait()一样,意思是执行wait()方法的这个线程test1要进入调用这个wait()方法的对象demoThread1的等待区了!!!
    wait()执行完后,释放demoThread1对象的锁,test2线程因为名字不是1而直接进入while循环,在循环中,每次time值加1,当加到10的整数倍的时候,test2线程执行notify,这里相当与this.notify, 也就是demoThread1.notify(),作用是告诉在demoThread1对象等待区中的线程:你们不用等了,可以出来了。在这里的效果就是test2让先前的test1恢复执行,然后test2调用wait()让自己进入demoThread1的等待区,接下来的事情就是test1和test2互相调换角色,直到两个线程的计数达到100,线程结束。
      

  4.   

    感谢楼上的,这才是csdn的好同志嘛。呵呵,马上给分
      

  5.   

    LBN1012(星空) ( ) 信誉:97  2006-6-1 1:15:57  得分: 34  
     
     
       
    在一个DemoThread对象中启动了两个线程test1和test2,test1在刚进入run的时候就会开始等待,在这里真正发生的事情是test1进入了DemoThread对象的等待区,在JAVA中任何一个对象都有自己的等待区(这也是为什么wait(),notify()和notifyAll()是Object类的方法而不是Thread类的方法的原因)。这里的wait()相当与this.wait(),效果和demoThread1.wait()一样,意思是执行wait()方法的这个线程test1要进入调用这个wait()方法的对象demoThread1的等待区了!!!
    wait()执行完后,释放demoThread1对象的锁,test2线程因为名字不是1而直接进入while循环,在循环中,每次time值加1,当加到10的整数倍的时候,test2线程执行notify,这里相当与this.notify, 也就是demoThread1.notify(),作用是告诉在demoThread1对象等待区中的线程:你们不用等了,可以出来了。在这里的效果就是test2让先前的test1恢复执行,然后test2调用wait()让自己进入demoThread1的等待区,接下来的事情就是test1和test2互相调换角色,直到两个线程的计数达到100,线程结束。  
     
    ==================================================================================   LBN1012(星空)说的不对,因为先调用了“testthread2.start();”。所以test2先执行,不过在遇到(!t.getName().equalsIgnoreCase("1")) 条件时,test2符合条件,所以就执行wait(),进入demoThread1的等待队列了。然后,就是test1执行,它不符合(!t.getName().equalsIgnoreCase("1")) 条件,所以跳过,继续下面的,也就是while (true) { … }中的循环,当test1在循环体中反复执行了10次,也就是test1对象中time等于10时,demoThread1.notify()被执行,notify()让demoThread1对象的等待队列中第一个线程也就是test2结束等待,进入就绪状态。最后,wait()被执行,demoThread1对象把test1放入等待队列。
        下面就是在就绪状态test2进入运行状态了,注意它不是重头从run()方法开始执行,而是从上次被阻塞的地方开始,继续向下执行……
        再接下来的事情就是test1和test2互相替换执行。LBN1012(星空)说的还是很清晰易懂的,大概是熬夜的原因吧,没看到条件前有“!”。
    顺便说一下,这段代码中if (!t.getName().equalsIgnoreCase("1")) {
                              synchronized (this) {
                             wait();
                            }
                            }
    才是亮点,如果没有它,程序就有一定的几率出问题。
      

  6.   

    synchronized (this) 
    两个线程都是对自己搞同步锁,有什么“交替执行”