Java再学习——sleep(), wait(), notify(), notifyAll()

  首先一点就是Thread.sleep(long millis)方法是Thread类的静态方法,其他三个wait(), notify()和notifyAll()都是Object类的方法。

  sleep(long millis)方法的调用能使当前线程暂定执行指定时间(但是并没有释放任何锁),然后再继续运行。相当于设个闹钟然后睡觉,要么时间到被闹钟叫醒,要么就被interrupt()叫醒,然后继续干活。

  wait()方法则是让当前线程放弃调用wait()方法的对象的锁同时进入等待锁状态,然后只有通过该对象的notify()和notifyAll()方法才可以重新让线程进入抢夺状态。

  notify()方法则是唤醒某个等待中的线程(任意的,没有规律可寻)进入抢夺状态。

  notifyAll()方法则是唤醒所有等待中的线程进入抢夺状态。

完整消费者例子如下:

public class APP {

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

        class User {
            private int value;

            public User(int v) {
                this.value = v;
            }

            public int getValue() {
                return value;
            }

            public void setValue(int value) {
                this.value = value;
            }

        }

        class Consumer extends Thread {
            private User user;

            public Consumer(User s) {
                user = s;
            }

            @Override
            public void run() {
                while (true) {
                    try {
                        synchronized (user) {
                            user.wait();
                            System.out.println("in " + getName()
                                    + " ,value -> " + user.getValue());
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        class Productor extends Thread {
            private User user;
            private int count = 0;

            public Productor(User s) {
                user = s;
            }

            @Override
            public void run() {
                while (true) {
                    try {
                        synchronized (user) {
                            int value = count++;
                            System.out.println("productor value is " + value);
                            user.setValue(value);
                            user.notify();
                        }
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        User user = new User(10);
Consumer consumer1
= new Consumer(user); consumer1.start(); Consumer consumer2 = new Consumer(user); consumer2.start(); Consumer consumer3 = new Consumer(user); consumer3.start(); Productor productor = new Productor(user); productor.start(); } }

代码说明:

  1,要wait和notify的对象,最好是个Javabean,基本数据类型和被处理过的String等,都不适合做这种多线程处理,因为这些存在赋值操作的变量,会让线程莫名的失去本以为理所当然的Monitor,而实际上都已经丢失了,当然就会报错java.lang.IllegalMonitorStateException,而只有操作对象本身就保证了只有一个Monitor,关键是看谁拿了而已。

  2,基于第一点,所以在操作该对象时必须要进行同步,也就是要保证当前对其的操作时,你是独立占有它的。如例子中用的synchronized关键字对user进行代码块同步。

  3,同步的时候一定要记得限定同步的范围,比如例子中如果把synchronized代码块包括到while层,如果放在Consumer类还好写,但是如果放在Productor类,那个就没有任何意义了,因为这样会使得当前线程一直占有该对象,别的对象就只有一直等待了。所以一定要在处理完后记得放开它。

  4,notifyAll会唤醒所有的wait线程,但是并不一定就会 一起运行,还是要看线程个人造化。

原文地址:https://www.cnblogs.com/wytings/p/4960654.html