黑马程序员技术交流社区

标题: sleep()和wait()有什么差别?搞线程的最爱 [打印本页]

作者: 鄢甲力    时间: 2011-8-3 11:30
标题: sleep()和wait()有什么差别?搞线程的最爱
关于线程的问题。。。。
作者: 匿名    时间: 2011-8-3 12:43
sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。对于wait的讲解一定要配合例子代码来说明,才显得自己真明白。[code]public class MultiThread {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                new Thread(new Thread1()).start();
                try {
                        Thread.sleep(10);
                } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                new Thread(new Thread2()).start();               
        }
       
       
        private static class Thread1 implements Runnable
        {

                @Override
                public void run() {
                        // TODO Auto-generated method stub
//由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器,我们这里不能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。
                        synchronized (MultiThread.class) {

                                System.out.println("enter thread1...");
                               
                                System.out.println("thread1 is waiting");
                                try {
                        //释放锁有两种方式,第一种方式是程序自然离开监视器的范围,也就是离开了synchronized关键字管辖的代码范围,另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。
                                        MultiThread.class.wait();
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                               
                                System.out.println("thread1 is going on...");
                                System.out.println("thread1 is being over!");                       
                        }
                }
               
        }
       
        private static class Thread2 implements Runnable
        {

                @Override
                public void run() {
                        // TODO Auto-generated method stub
                        synchronized (MultiThread.class) {
                       
                                System.out.println("enter thread2...");
                               
                                System.out.println("thread2 notify other thread can release wait status..");
//由于notify方法并不释放锁, 即使thread2调用下面的sleep方法休息了10毫秒,但thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。

                                MultiThread.class.notify();
                               
                                System.out.println("thread2 is sleeping ten millisecond...");
                                try {
                                        Thread.sleep(10);
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                               
                                System.out.println("thread2 is going on...");
                                System.out.println("thread2 is being over!");
                               
                        }
                }
               
        }       

}
        [/code]
作者: 匿名    时间: 2011-8-3 13:04
sleep是线程被调用时,占着cpu去睡觉,其他线程不能占用cpu,os认为该线程正在工作,不会让出系统资源,wait是进入等待池等待,让出系统资源,其他线程可以占用cpu,一般wait不会加时间限制,因为如果wait的线程运行资源不够,再出来也没用,要等待其他线程调用notifyall方法唤醒等待池中的所有线程,才会在进入就绪序列等待os分配系统资源,
sleep是静态方法,是谁掉的谁去睡觉,就算是在main线程里调用了线程b的sleep方法,实际上还是main去睡觉,想让线程b去睡觉要在b的代码中掉sleep

sleep(100L)是占用cpu,线程休眠100毫秒,其他进程不能再占用cpu资源,wait(100L)是进入等待池中等待,交出cpu等系统资源供其他进程使用,在这100毫秒中,该线程可以被其他线程notify,但不同的是其他在等待池中的线程不被notify不会出来,但这个线程在等待100毫秒后会自动进入就绪队列等待系统分配资源,换句话说,sleep(100)在100毫秒后肯定会运行,但wait在100毫秒后还有等待os调用分配资源,所以wait100的停止运行时间是不确定的,但至少是100毫秒。
作者: 匿名    时间: 2011-8-4 12:10
sleep()、suspend()、resume()方法不推荐使用,推荐使用wait()、notify()、notifyAll()。
     sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非
         (a)“醒来”的线程具有更高的优先级。  
         (b)正在运行的线程因为其它原因而阻塞。

    wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

      当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。

     waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
作者: 匿名    时间: 2011-8-4 14:35
当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。wait()方法只能在同步控制块中使用。
    对于sleep方法,再经过了规定的时间后,相应的线程会自动进入就绪状态,不需要其它的线程叫醒,也不会丢失当前线程对任何对象的同步锁
    若需要线程同步运行,进行数据交换时,使用wait() notify()方法的组合更好些




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2