http://blog.csdn.net/kobejayandy/article/details/9362141
http://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html
JVM中可以生成的最大线程数量由JVM的堆内存大小、Thread的Stack内存大小、系统最大可创建的线程数量(Java线程的实现是基于底层系统的线程机制来实现的,Windows下_beginthreadex,Linux下pthread_create)三个方面影响。
wait():作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
调用wait方法需要注意几点:
第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复a执行后继续执行的条件不满足却继续执行的情况。
第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
synchronized关键字:
第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
获取对象锁进入运行状态。
什么意思呢?
举个列子说明:
1 /** 2 * 3 */ 4 package com.b510.test; 5 6 /** 7 * java中的sleep()和wait()的区别 8 * @author Hongten 9 * @date 2013-12-10 10 */ 11 public class TestD { 12 13 public static void main(String[] args) { 14 new Thread(new Thread1()).start(); 15 try { 16 Thread.sleep(5000); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 new Thread(new Thread2()).start(); 21 } 22 23 private static class Thread1 implements Runnable{ 24 @Override 25 public void run(){ 26 synchronized (TestD.class) { 27 System.out.println("enter thread1..."); 28 System.out.println("thread1 is waiting..."); 29 try { 30 //调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池 31 TestD.class.wait(); 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 System.out.println("thread1 is going on ...."); 36 System.out.println("thread1 is over!!!"); 37 } 38 } 39 } 40 41 private static class Thread2 implements Runnable{ 42 @Override 43 public void run(){ 44 synchronized (TestD.class) { 45 System.out.println("enter thread2...."); 46 System.out.println("thread2 is sleep...."); 47 //只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。 48 TestD.class.notify(); 49 //================== 50 //区别 51 //如果我们把代码:TestD.class.notify();给注释掉,即TestD.class调用了wait()方法,但是没有调用notify() 52 //方法,则线程永远处于挂起状态。 53 try { 54 //sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程, 55 //但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。 56 //在调用sleep()方法的过程中,线程不会释放对象锁。 57 Thread.sleep(5000); 58 } catch (Exception e) { 59 e.printStackTrace(); 60 } 61 System.out.println("thread2 is going on...."); 62 System.out.println("thread2 is over!!!"); 63 } 64 } 65 } 66 }
运行效果:
enter thread1... thread1 is waiting... enter thread2.... thread2 is sleep.... thread2 is going on.... thread2 is over!!! thread1 is going on .... thread1 is over!!!
如果注释掉代码:
1 TestD.class.notify();
运行效果:
enter thread1...
thread1 is waiting...
enter thread2....
thread2 is sleep....
thread2 is going on....
thread2 is over!!!
且程序一直处于挂起状态。