精华内容
下载资源
问答
  • sleep和wait

    2012-07-04 23:22:34
    之前面试, 背了下sleep和wait的区别,蒙混过关了。 最近又准备面试, 发现sleep和wait的区别, 理解得还是不够。 于是想用段代码来验证下以加深下印象   一开始这么写的   public class SleepAndWait { /*...

    之前面试, 背了下sleep和wait的区别,蒙混过关了。 最近又准备面试, 发现sleep和wait的区别, 理解得还是不够。 于是想用段代码来验证下以加深下印象

     

    一开始这么写的

     

    public class SleepAndWait {
    
    	/**
    	 * @param args
    	 * @throws InterruptedException
    	 */
    	public static void main(String[] args) throws InterruptedException {
    
    		
    		// runWait();
    		runSleep();
    	}
    
    	static void runSleep() throws InterruptedException {
    		Sleep s = new Sleep();
    		Thread t = new Thread(s, "Sleep线程");
    		System.out.println("程序开始");
    		t.start();
    		Thread.sleep(1000);
    
    		s.testSyncSleep();
    	
    	}
    
    }
    
    class Sleep implements Runnable {
    
    	void testSleep() {
    		System.out.println("非sync方法可以执行");
    
    	}
    
    	synchronized void testSyncSleep() {
    		System.out.println("sync方法可以执行");
    	}
    
    	@Override
    	public void run() {
    
    		System.out.println(Thread.currentThread().getName() + "开始休眠5s");
    		try {
    				Thread.sleep(5000);
    
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName() + "休眠完成");
    
    	}
    }

     一运行,问题马上出来了。 不是说,sleep不会释放对象锁吗?怎么执行sleep休眠时还可以运行testSyncSleep方法

     

    搜了下资料,发现不少人也有同样的问题。

     

    http://www.iteye.com/topic/1038812

    http://www.iteye.com/problems/21645

     

    归根结底, 真正的问题是, sleep到底是持有谁的锁?

     

    到这里, 差不多能发现上面代码问题所在了, sleep前没加任何锁, 当然也就无法验证sleep不会释放对象锁的问题

     

    重写了下代码,验证了下, 问题差不多明白了。

     

    public class SleepAndWait {
    
    	/**
    	 * @param args
    	 * @throws InterruptedException
    	 */
    	public static void main(String[] args) throws InterruptedException {
    
    		
    		runWait();
    		// runSleep();
    	}
    	
    	static void runWait() throws InterruptedException {
    		Wait s2 = new Wait();
    		Thread t2 = new Thread(s2, "Wait线程");
    		System.out.println("程序开始");
    		t2.start();
    		Thread.sleep(1000);
    		
    
    		
    		/*
    		 * s2.testSyncWait 输出结果
    		 * 
    		 * 程序开始
    		 * Wait线程开始休眠5s
    		 * sync方法可以执行
    		 * Wait线程休眠完成
    		 */
    		// s2.testSyncWait();
    		
    		/*
    		 * s2.testWait 输出结果
    		 * 
    		 * 程序开始
    		 * Wait线程开始休眠5s
    		 * 非sync方法可以执行
    		 * Wait线程休眠完成
    		 */
    		// s2.testWait();
    		
    		// 注意, 和非sync方法相比, sync方法明显没有被阻塞直到Wait线程休眠完成, 
    		// 也就是说, wait时已经释放对象锁			
    	}
    	
    	static void runSleep() throws InterruptedException {
    		Sleep s = new Sleep();
    		Thread t = new Thread(s, "Sleep线程");
    		System.out.println("程序开始");
    		t.start();
    		Thread.sleep(1000);
    		
    		/*
    		 * s.testSleep() 输出结果
    		 * 
    		 * 程序开始 
    		 * Sleep线程开始休眠5s 
    		 * 非sync方法可以执行 
    		 * Sleep线程休眠完成
    		 */
    		//s.testSleep();	
    		
    		/*
    		 * s.testSyncSleep() 输出结果 
    		 * 程序开始 
    		 * Sleep线程开始休眠5s 
    		 * Sleep线程休眠完成 
    		 * sync方法可以执行
    		 */
    		//s.testSyncSleep();
    		
    		// 注意, 和非sync方法相比, sync方法明显被阻塞直到Sleep线程休眠完成, 
    		// 也就是说, sleep时没有释放对象锁		
    	}
    
    }
    
    class Wait implements Runnable {
    
    	void testWait() {
    		System.out.println("非sync方法可以执行");
    	}
    	
    	synchronized void testSyncWait() {
    		System.out.println("sync方法可以执行");
    	}
    	
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + "开始休眠5s");
    		try {
    			synchronized (this) {
    				wait(5000);
    			}
    
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName() + "休眠完成");
    	}
    	
    }
    
    class Sleep implements Runnable {
    
    	void testSleep() {
    		System.out.println("非sync方法可以执行");
    
    	}
    
    	synchronized void testSyncSleep() {
    		System.out.println("sync方法可以执行");
    	}
    
    	@Override
    	public void run() {
    
    		System.out.println(Thread.currentThread().getName() + "开始休眠5s");
    		try {
    			synchronized (this) {
    				Thread.sleep(5000);
    			}
    
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName() + "休眠完成");
    
    	}
    }
     

    参考

    java 之sleep(), yield(), wait(), notify(), join()的区别

    http://dylanxu.iteye.com/blog/1322066

     

    展开全文
  • Sleep和wait

    2019-03-18 21:04:00
    sleep()和wait()的区别及wait方法的一点注意事项 一.查看API sleep是Thread类的方法,导致此线程暂停执行指定时间,给其他线程执行机会,但是依然保持着监控状态,过了指定时间会自动恢复,调用sleep方法...

    sleep()和wait()的区别及wait方法的一点注意事项

     

    一.查看API

    sleep是Thread类的方法,导致此线程暂停执行指定时间,给其他线程执行机会,但是依然保持着监控状态,过了指定时间会自动恢复,调用sleep方法不会释放锁对象。

    当调用sleep方法后,当前线程进入阻塞状态。目的是让出CPU给其他线程运行的机会。但是由于sleep方法不会释放锁对象,所以在一个同步代码块中调用这个方法后,线程虽然休眠了,但其他线程无法访问它的锁对象。这是因为sleep方法拥有CPU的执行权,它可以自动醒来无需唤醒。而当sleep()结束指定休眠时间后,这个线程不一定立即执行,因为此时其他线程可能正在运行。

    wait方法是Object类里的方法,当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时释放了锁对象,等待期间可以调用里面的同步方法,其他线程可以访问,等待时不拥有CPU的执行权,否则其他线程无法获取执行权。当一个线程执行了wait方法后,必须调用notify或者notifyAll方法才能唤醒,而且是随机唤醒,若是被其他线程抢到了CPU执行权,该线程会继续进入等待状态。由于锁对象可以时任意对象,所以wait方法必须定义在Object类中,因为Obeject类是所有类的基类。

    二.是否可以传入参数

    sleep()方法必须传入参数,参数就是休眠时间,时间到了就会自动醒来。

    wait()方法可以传入参数也可以不传入参数,传入参数就是在参数结束的时间后开始等待,不穿如参数就是直接等待。

    三.是否需要捕获异常

    sleep方法必须要捕获异常,而wait方法不需要捕获异常。sleep方法属于Thread类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。

    wait属于Object的成员方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生。

    四.作用范围

    wait、notify和notifyAll方法只能在同步方法或者同步代码块中使用,而sleep方法可以在任何地方使用。但是注意sleep是静态方法,也就是说它只对当前对象有效。通过对象名.sleep()想让该对象线程进入休眠是无效的,它只会让当前线程进入休眠。

    五.调用者的区别

    首先为什么wait、notify和notifyAll方法要和synchronized关键字一起使用?

    因为wait方法是使一个线程进入等待状态,并且释放其所持有的锁对象,notify方法是通知等待该锁对象的线程重新获得锁对象,然而如果没有获得锁对象,wait方法和notify方法都是没有意义的,因此必须先获得锁对象再对锁对象进行进一步操作于是才要把wait方法和notify方法写到同步方法和同步代码块中了。

    由此可知,wait和notify、notifyAll方法是由确定的对象即锁对象来调用的,锁对象就像一个传话的人,他对某个线程说停下来等待,然后对另一个线程说你可以执行了(实质上是被捕获了),这一过程是线程通信。sleep方法是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,运行的主动权是由当前线程来控制(拥有CPU的执行权)。

    其实两者的区别都是让线程暂停运行一段时间,但本质的区别一个是线程的运行状态控制,一个是线程间的通信。

    六.wait方法(线程通信)的一些注意事项

    例如以下代码:

    当线程print1获得了锁对象(this)后进行判断,如果不满足条件(flag == 1)无法继续执行下面的代码,于是进入wait状态。在另一个线程print3中,由于改变了flag,使得线程print1的判断条件满足了,线程print1就会被唤醒。

    复制代码
    class Printer {
        private int flag = 1;
        public void print1() throws Exception {
            synchronized(this) {
                while(flag != 1) {
                    this.wait();    
                }
                System.out.print("1");
                System.out.print("2");
                System.out.print("3");
                System.out.print("4");
                System.out.println();
                flag = 2;
                this.notifyAll();
            }
        }
        public void print2() throws Exception {
            synchronized(this) {
                while(flag != 2) {
                    this.wait();
                }
                System.out.print("5");
                System.out.print("6");
                System.out.print("7");
                System.out.print("8");
                System.out.println();
                flag = 3;
                this.notifyAll();
            }
        }
        public void print3() throws Exception {
            synchronized(this) {
                while(flag != 3) {
                    this.wait();
                }
                System.out.print("A");
                System.out.print("B");
                System.out.print("C");
                System.out.print("D");
                System.out.println();
                flag = 1;
                this.notifyAll();
            }
        }
    }
    复制代码

     

    注意事项:

    1.调用wait方法和notify、notifyAll方法前必须获得对象锁,也就是必须写在synchronized(锁对象){......}代码块中。

    2.当线程print1调用了wait方法后就释放了对象锁,否则其他线程无法获得对象锁,也就无法唤醒线程print1。

    3.当this.wait()方法返回后,线程必须再次获得对象锁后才能继续执行。

    4.如果另外两个线程都在wait,则正在执行的线程调用notify方法只能唤醒一个正在wait的线程(公平竞争,由JVM决定)。

    5.当使用notifyAll方法后,所有wait状态的线程都会被唤醒,但是只有一个线程能获得锁对象,必须执行完while(condition){this.wait();}后才能获得对象锁。其余的需要等待该获得对象锁的线程执行完释放对象锁后才能继续执行。

    6.当某个线程调用notifyAll方法后,虽然其他线程被唤醒了,但是该线程依然持有着对象锁,必须等该同步代码块执行完(右大括号结束)后才算正式释放了锁对象,另外两个线程才有机会执行。

     

     wait()与sleep()的区别
    sleep()方法是Thread类的静态方法,不涉及到线程间同步概念,仅仅为了让一个线程自身获得一段沉睡时间。sleep可以在任何地方使用。
    wait()方法是object类的方法,解决的问题是线程间的同步,该过程包含了同步锁的获取和释放,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify()方法才会重新激活调用者。
    注意:线程调用notify()之后,只有该线程完全从 synchronized代码里面执行完毕后,monitor才会被释放,被唤醒线程才可以真正得到执行权。

    wait与notify是Java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多优秀的同步模型。

          synchronized(this){}等价与public synchronized void method(){.....}

          同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。

          首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

          java.lang.IllegalMonitorStateException: current thread not owner

          在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。

          所以,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并允许它去获得锁,notifyAll是唤醒所有等待这个对象的线程并允许它们去获得对象锁,只要是在synchronied块中的代码,没有对象锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。

           顺便说一下notifyall,虽然是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,需要注意一下。

    转载于:https://www.cnblogs.com/gavin-yao/p/10528272.html

    展开全文
  • sleep和 wait

    2017-07-20 20:51:00
    转载于:https://www.cnblogs.com/bee-home/p/7214432.html

     

    转载于:https://www.cnblogs.com/bee-home/p/7214432.html

    展开全文
  • 08 sleep和wait区别

    2020-09-06 14:18:01
    09 sleep和wait区别 文章目录09 sleep和wait区别sleep和wait区别演示 sleep和wait区别 sleep是Thread的方法,wait是Object的方法 sleep不会释放锁,但是wait会释放锁,并且将线程添加到该对象监视器(monitor)的...

    09 sleep和wait区别

    sleep和wait区别

    • sleep是Thread的方法,wait是Object的方法
    • sleep不会释放锁,但是wait会释放锁,并且将线程添加到该对象监视器(monitor)的等待队列中
    • sleep使用的时候不依赖同步锁,而使用wait的时候必须加同步锁
    • sleep不需要被唤醒,但是wait是需要唤醒的

    演示

    public class DifferenceOfWaitAndSleep {
    
        private final static Object LOCK = new Object();
    
        public static void main(String[] args) {
            // m1();
            //m2();
            m3();
        }
    
    
        public static void m1() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        // 这里没有加锁,运行,就会抛出一个异常IllegalMonitorStateException
        public static void m2() {
            try {
                LOCK.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        // 这里加锁,运行,就不会抛出一个异常IllegalMonitorStateException
        public static void m3() {
            synchronized (LOCK){
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        public static void m4() {
            synchronized (LOCK){
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    @Slf4j
    public class DifferenceOfWaitAndSleep2 {
    
        private final static Object LOCK = new Object();
    
        public static void main(String[] args) {
            // 运行发现,T1进去之后休眠3秒,T2才会执行,也就是说T1 Sleep的时候没有释放锁,T2抢不到执行权
            /*Stream.of("T1","T2").forEach(t -> {
                new Thread(t){
                    @Override
                    public void run() {
                        m1();
                    }
                }.start();
            });*/
           // T1和T2几乎同时enter,也就是说无论T1还是T2先抢到执行权,wait之后,立马就会释放锁,剩下的那个就会抢到执行权执行
            // 所以几乎同时enter
            Stream.of("T1","T2").forEach(t -> {
                new Thread(t){
                    @Override
                    public void run() {
                        m2();
                    }
                }.start();
            });
    
        }
    
    
        public static void m1() {
            synchronized (LOCK){
                try {
                    log.info("{} enter");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
        public static void m2() {
            synchronized (LOCK){
                try {
                    log.info("{} enter");
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    
    展开全文
  • sleep和wait的区别是面试中一个非常常见的问题,因为从表象来看,好像sleep和wait都能使线程处于阻塞状态,但是却有着本质上的却别。这篇文章就来好好分析一下。整体的区别其实是有四个:1、sleep是线程中的方法,...
  • 本文较为详细的分析了C#中sleep和wait的区别。分享给大家供大家参考。具体分析如下: sleep和wait都是使线程暂时停止执行的方法,但它们有很大的不同。 ①. sleep是线程类Thread 的方法,它是使当前线程暂时睡眠,...
  • sleep和wait的区别

    2020-12-13 16:22:29
    Java中sleep和wait的异同? 相同点: sleep()和wait()都会使当前线程进入阻塞状态。 sleep()和wait()都需要捕获异常。 public final native void wait(long timeout) throws InterruptedException; public ...
  • 在JAVA的学习中,不少人会把sleep和wait搞混,认为都是做线程的等待,下面主要介绍下这俩者是什么,及了解它们之间的差异和相似之处。一般差异简单来说,wait()是一个用于线程同步的实例方法。因为定义在java.lang....
  • sleep wait 区别

    千次阅读 2017-05-14 22:15:57
    sleep和wait区别: 区别一:所属对象不一样 区别一:对锁的控制权
  • sleep wait 的区别

    2021-02-20 15:28:13
    sleep wait 的区别 1.类不同 sleep() 方法是属于 Thread 类中的; wait() 方法属于 Object 类中的; 2.锁处理方式不同 sleep() 方法在调用时不会释放锁(即之前请求的锁不会释放,没有锁也不会请求); wait() ...
  • 同学你好:首先我们可以看一看 sleep wait 的区别:(1)wait() 是 Object 中定义的 native 方法publicfinalnativevoidwait(longtimeout)throwsInterruptedException;所以每一个类的实例都可以调用这个方法。wait()...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,225
精华内容 2,090
关键字:

sleep和wait