A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张淼 中级黑马   /  2012-9-22 08:46  /  2236 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

wait方法和sleep方法这里理解的一直不是很清楚,只记住了他们的区别:sleep方法不会释放锁,而wait方法会释放锁。
这里的释放与不释放是具体怎样体现的呢?能否为我各举一个例子,体现他们之间的区别。

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

5 个回复

倒序浏览
这两者的施加者是有本质区别的.
sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定.好比如说,我要做的事情是 "点火->烧水->煮面",而当我点完火之后我不立即烧水,我要休息一段时间再烧.对于运行的主动权是由我的流程来控制
而wait(),首先,这是由某个确定的对象来调用的,将这个对象理解成一个传话的人,当这个人在某个线程里面说"暂停!",也是 thisOBJ.wait(),这里的暂停是阻塞,还是"点火->烧水->煮饭",thisOBJ就好比一个监督我的人站在我旁边,本来该线 程应该执行1后执行2,再执行3,而在2处被那个对象喊暂停,那么我就会一直等在这里而不执行3,但正个流程并没有结束,我一直想去煮饭,但还没被允许, 直到那个对象在某个地方说"通知暂停的线程启动!",也就是thisOBJ.notify()的时候,那么我就可以煮饭了,这个被暂停的线程就会从暂停处 继续执行. 其实两者都可以让线程暂停一段时间,但是本质的区别是一个线程的运行状态控制,一个是线程之间的通讯的问题 在java.lang.Thread类中,提供了sleep(),而java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程sleep()可以将一个线程睡眠,参数可以指定一个时间。而wait()可以将一个线程挂起,直到超时或者该线程被唤醒。   
wait有两种形式wait()和wait(milliseconds).sleep和wait的区别有:
1,这两个方法来自不同的类分别是Thread和Object  
2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在    任何地方使用   synchronized(x){      x.notify()     //或者wait()   }   
4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常wait()、notify()、notifyAll()是不是只能在非静态同步控制方法或非静态方法的同步控制块里使用? 注意:非静态,同步控制。 也就是说,调用这些方法前必须“拥有”(获取)对象的锁,而获取类的锁没用。也可以在静态方法里对对象使用,但一定要在能够取得这个对象锁的同步控制块里用。例如在main方法里写一个临界快,获得一个对象的锁,然后对这个对象调用wait方法。 但如果获取类的锁(例如在临界块里获得类名.class的锁)就不行。因为这三个方法不是静态方法,需要一个对象来调用他们,获得类的锁并不代表获得了对象的锁,所以运行会抛出异常。

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
wait()是Object的方法
sleep()是Thread的方法

虽然Thread是Object的子类,
但这两个方法根本就不会有什么混淆的东西

static void sleep(long millis)
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
static void sleep(long millis, int nanos)
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
void notify()
          唤醒在此对象监视器上等待的单个线程。
void notifyAll()
          唤醒在此对象监视器上等待的所有线程。
String toString()
          返回该对象的字符串表示。
void wait()
          在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
void wait(long timeout)
          在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
void wait(long timeout, int nanos)
          在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 程金 于 2012-9-22 09:41 编辑

注意先执行代码看执行效果,再理解.
  1. <font color="Red">怎么用不了红字了</font>
  2.   
  3. <div class="blockcode"><blockquote>package test;

  4. public class Test {
  5.           public static void main(String[] args) throws Exception {
  6.                 ThreadTest threadTest = new ThreadTest();
  7.                 new Thread(threadTest).start();
  8.                 threadTest.secondMethod();
  9.                
  10.             }
  11.         
  12. }
  13.          class ThreadTest implements Runnable {
  14.             int number = 10;
  15.             public void firstMethod() throws Exception {
  16.                 synchronized (this) {
  17.                     number += 10;
  18.                     System.out.println(number);
  19.                 }
  20.             }
  21.             public void secondMethod() throws Exception {
  22.                 synchronized (this) {
  23.                   
  24.               //(休息3S,阻塞线程)
  25.                     
  26.                   
  27.                         
  28.                     Thread.sleep(3000);//当这个线程(main线程)sleep的时候,它没有释放锁,
  29.                     //所以另外一线程也无法执行firstMethod(),处于阻塞状态,3秒过后,此线程苏醒开始执行
  30.                     //执行完毕,另一线程立刻执行,效果是:3秒后 两线程输出语句
  31.                     //
  32.                     
  33.                     //this.wait(2000);//当使用wait的时候,由于它释放了锁,另外一线程可以获得锁执行firstMethod()
  34.                     //控制台立马打印一条firstmothod计算结果语句.然后3秒后,main线程苏醒,打印一条计算结果语句
  35.                     number *= 200;
  36.                     System.out.println(number);
  37.                 }
  38.             }
  39.             @Override
  40.             public void run() {
  41.                 try {
  42.                     firstMethod();
  43.                 } catch (Exception e) {
  44.                     e.printStackTrace();
  45.                 }
  46.             }

  47.            
  48.         }
复制代码

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。对于wait的讲解一定要配合例子代码来说明,才显得自己真明白。
package com.huawei.interview;

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!");
                               
                        }
                }
               
        }       

}

评分

参与人数 1技术分 +1 收起 理由
王德升 + 1 赞一个!

查看全部评分

回复 使用道具 举报
非常感谢各位,讲解的很细致,但还是感觉有代码的比较好理解。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马