• 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线程,但是并不一定就会 一起运行,还是要看线程个人造化。

  • 相关阅读:
    jQuery获取鼠标事件源
    windows中MongoDB安装和环境搭建
    前端获取后台数据的方法:ajax、axios、fetch
    浅谈:easy-mock的使用
    安全篇-AES/RSA加密机制
    PHP开发api接口安全验证
    Ajax简单实现文件异步上传的多种方法
    PHP7有没有你们说的那么牛逼
    基于laravel框架构建最小内容管理系统
    redis用法分析
  • 原文地址:https://www.cnblogs.com/wytings/p/4960654.html
Copyright © 2020-2023  润新知