Java线程的wait() 与notify()

来源:互联网 发布:淘宝祛痘产品有用吗 编辑:程序博客网 时间:2024/05/22 06:36

       java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。

wait() 的方法是Object的方法,不是线程的方法,作用是让线程挂起,处于等待状态,之后可以调用notify()的方法激活线程。

      也可以这样使用,线程处于运行时,判断到某个状态时调用wait(),这样线程处于等待状态,在其他地方调用object的notify的方法时,也必须获取到该线程的同步锁:

synchronized (object) {boject.notify();}

       对于notify()方法,如果多个线程处于等待状态,那么被唤醒的线程由VM选择决定,调用了notify的线程将放弃对对象的锁,其他线程会尝试获得该对象的锁,获得该锁的对象将被唤醒:

notify()、wait()的方法必须要在获得锁的情况下使用,比如说在同步代码里面:

synchronized (object) {boject.notify();}


所以注意的是:

1.wait()与notify()的方法是object的共同属性,此时object当成一个同步锁。

2.wait()的方法会让线程挂起并释放锁,而notify()的方法会将挂起的线程唤醒同时在同步代码块结束后释放锁。

3.wait()与notify的方法是已经获取了锁的情况下,获取对象的monitor的方法有:

    a.执行这个object的synchronized方法。

   b.执行一段synchronized代码,并基于这个object的同步。

   c.如果boject是class类,可以执行它的synchronized static 方法。

简单理解:wait()与notify()都是获取到同步锁的情况下才能执行的,语法上就是写在synchronized中。wait()的作用是放弃同步锁并使线程进入休眠,直到其他线程获取到同步锁使用notify()后才唤醒。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。

使用:

1.同步锁的理解

  启动十个线程线程,代码如下:

public static void main(String[] args) {Object a = new Object();for (int i = 0; i < 10; i++) {new Thread(new test2(a, i + "")).start();}}public static class test2 implements Runnable {Object lock;String name;public test2(Object lock, String name) {this.lock = lock;this.name = name;}public void run() {System.out.println(name + "开始执行");double f = 66;while (f < 30000000.0) {f = f + 0.05;}System.out.println(name + "结束执行");}}

执行结果如下:

2开始
0开始
7开始
4开始
6开始
8开始
3开始
1开始
5开始
9开始
8结束
5结束
4结束
0结束
2结束
6结束
3结束
1结束
7结束
9结束

总结:十个线程执行差不多是同时执行的,因为在循环过程中执行了耗时操作,所以所有线程执行了开始执行后才会执行结束执行操作,最先开始的不一定最先结束,因为是使用cup是随机抢占的。


加了同步锁:

public static class test2 implements Runnable {Object lock;String name;public test2(Object lock, String name) {this.lock = lock;this.name = name;}public void run() {synchronized (lock) {System.out.println(name + "开始");double f = 66;while (f < 30000000.0) {f = f + 0.05;}System.out.println(name + "结束");}}}

执行结果如下:

0开始
0结束
4开始
4结束
3开始
3结束
2开始
2结束
1开始
1结束


总结
:进行同步后,其他线程会等待已经获取到同步锁的线程完成操作并将同步锁释放,释放后线程随机去抢同步锁,获取到同步锁的线程才能执行。


让线程执行了开始后就调用wait()

public static class test2 implements Runnable {Object lock;String name;public test2(Object lock, String name) {this.lock = lock;this.name = name;}public void run() {synchronized (lock) {System.out.println(name + "开始");try {//放弃锁并使当前线程休眠lock.wait();} catch (InterruptedException e) {e.printStackTrace();}double f = 66;while (f < 30000000.0) {f = f + 0.05;}System.out.println(name + "结束");}}}

打印结果如下:

0开始
2开始
1开始
3开始
4开始

总结:所有线程都调用了wait()后暂停了,由于没有唤醒所以都没有执行下面的操作。


让其中一个线程唤醒其他线程:

public static class test2 implements Runnable {Object lock;String name;public test2(Object lock, String name) {this.lock = lock;this.name = name;}public void run() {synchronized (lock) {System.out.println(name + "开始");try {                                //如果是第四个线程,唤醒其他的线程if (name.equals("4")) {lock.notifyAll();//lock.wait();如果加了这个后,第四个线程不会执行下面的操作} else {// 放弃锁并使当前线程休眠lock.wait();}} catch (InterruptedException e) {e.printStackTrace();}double f = 66;while (f < 30000000.0) {f = f + 0.05;}System.out.println(name + "结束");}}}


打印如下:

0开始
2开始
1开始
3开始
4开始
4结束
3结束
1结束
2结束
0结束

总结:唤醒其他线程后,那些线程将随机抢占同步锁执行下面的操作。值得注意的是,notify的方法是唤醒其他线程但是不会立即放弃同步锁,wait()是会立即放弃同步锁的。


转载注明出处:http://blog.csdn.net/u014614038/article/details/49020147



0 0
原创粉丝点击