关于wait和sleep方法的区别

来源:互联网 发布:免费钣金放样软件 编辑:程序博客网 时间:2024/06/05 06:31

 

public class Test {

           public static void main(String[] args) throws Exception {

                 ThreadTest threadTest = new ThreadTest();

                 new Thread(threadTest).start();

                 threadTest.secondMethod();

                

             }

         

 }

          class ThreadTest implements Runnable {

             int number = 10;

             public void firstMethod() throws Exception {

                 synchronized (this) {

                     number += 10;

                     System.out.println(number);

                 }

             }

             public void secondMethod() throws Exception {

                 synchronized (this) {

                   

               //(休息3S,阻塞线程)

                     

                   

                         

                     Thread.sleep(3000);//当这个线程(main线程)sleep的时候,它没有释放锁,

                     //所以另外一线程也无法执行firstMethod(),处于阻塞状态,3秒过后,此线程苏醒开始执行

                     //执行完毕,另一线程立刻执行,效果是:3秒后两线程输出语句

                     //

                     

                     //this.wait(2000);//当使用wait的时候,由于它释放了锁,另外一线程可以获得锁执行firstMethod()

                     //控制台立马打印一条firstmothod计算结果语句.然后3秒后,main线程苏醒,打印一条计算结果语句

                     number *= 200;

                     System.out.println(number);

                 }

             }

             @Override

             public void run() {

                 try {

                     firstMethod();

                 } catch (Exception e) {

                     e.printStackTrace();

                 }

             }

 

            

         }

----------------------------------------------分割线------------------------------------------------

 

sleep就是正在执行的线程主动让出cpucpu去执行其他线程,在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和这个Thread1this不是同一个对象。我们用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!");

}
}



}

 

----------------------------------------------分割线------------------------------------------------

这两者的施加者是有本质区别的
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).sleepwait的区别有: 
1
,这两个方法来自不同的类分别是ThreadObject 
2
,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。 
3
waitnotifynotifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 synchronized(x){ x.notify() //或者wait() } 
4,sleep
必须捕获异常,而waitnotifynotifyAll不需要捕获异常wait()notify()notifyAll()是不是只能在非静态同步控制方法或非静态方法的同步控制块里使用?注意:非静态,同步控制。也就是说,调用这些方法前必须拥有(获取)对象的锁,而获取类的锁没用。也可以在静态方法里对对象使用,但一定要在能够取得这个对象锁的同步控制块里用。例如在main方法里写一个临界快,获得一个对象的锁,然后对这个对象调用wait方法。但如果获取类的锁(例如在临界块里获得类名.class的锁)就不行。因为这三个方法不是静态方法,需要一个对象来调用他们,获得类的锁并不代表获得了对象的锁,所以运行会抛出异常。

 

 

 

原创粉丝点击