Java使用wait/notify实现线程间通信下篇

 更新时间:2022年12月12日 15:45:25   作者:爱吃南瓜糕的北络  
wait()和notify()是直接隶属于Object类,也就是说所有对象都拥有这一对方法,下面这篇文章主要给大家介绍了关于使用wait/notify实现线程间通信的相关资料,需要的朋友可以参考下

上一节针对wait/notify实现线程间通信的基本概念做了讲解(Java使用wait/notify实现线程间通信上篇),本节继续针对wait/notify实现线程间通信的其他知识点及特性进行讲解。

1. 当 interrupt() 方法遇到 wait() 方法

当线程调用锁对象的wait() 方法使线程呈等待状态时,调用线程对象的 interrupt() 方法会出现 InterruptedException 异常。

public class ThreadC7 {
    @Test
    public void test1() {
        try {
            Object obj = new Object();
            ThreadC7A threadC7A = new ThreadC7A(obj);
            threadC7A.start();
            Thread.sleep(2000);
            threadC7A.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ServiceC7 {
    public void testMethod(Object obj) {
        try {
            synchronized (obj) {
                System.out.println("begin wait");
                obj.wait();
                System.out.println("begin end");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("出现异常了,wait状态的线程被interrupt了!");
        }
    }
}
class ThreadC7A extends Thread {
    private Object obj;
    public ThreadC7A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC7 serviceC7 = new ServiceC7();
        serviceC7.testMethod(obj);
    }
}

执行结果:

2. notify() 只通知一个线程

调用方法notify()一次只随机通知一个线程进行唤醒。

public class ThreadC8 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC8A threadC8A = new ThreadC8A(obj);
        threadC8A.setName("threadC8A");
        threadC8A.start();
        ThreadC8B threadC8B = new ThreadC8B(obj);
        threadC8B.setName("threadC8B");
        threadC8B.start();
        ThreadC8C threadC8C = new ThreadC8C(obj);
        threadC8C.setName("threadC8C");
        threadC8C.start();
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            obj.notify();
        }
        while (Thread.activeCount() > 1) {
        }
    }
}
class ServiceC8 {
    public void service(Object obj) {
        try {
            synchronized (obj) {
                String threadName = Thread.currentThread().getName();
                System.out.println("begin wait,Thread Name:[" + threadName + "]");
                obj.wait();
                System.out.println("end wait,Thread Name:[" + threadName + "]");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ThreadC8A extends Thread {
    private Object obj;
    public ThreadC8A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8B extends Thread {
    private Object obj;
    public ThreadC8B(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8C extends Thread {
    private Object obj;
    public ThreadC8C(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}

执行结果:

程序运行的效果如图所示,可以看出方法notify()仅随机唤醒一个线程。

当多次调用notify()方法时,会随机将等待wait状态的线程进行唤醒。更改代码如下:

再次运行,程序运行效果如图所示,可以看出所有的线程全部被唤醒。

多次调用notify()方法可唤醒全部WAITING中的线程。

3. notifyAll() 唤醒所有线程

前面的示例中通过多次调用 notify() 方法来实现唤醒3个线程,但并不能保证系统中仅有3个线程,也就是若notify()方法的调用次数小于线程对象的数量,会出现有部分线程对象无法被唤醒的情况。为了唤醒全部线程,可以使用notifyAll()方法。

更改代码如下:

再次运行,程序运行效果如图所示,可以看出所有的线程全部被唤醒。

4. 方法 wait(long)的使用

带一个参数的wait(long) 方法的功能是等待某一时间内是否有现成对锁进行唤醒,如果超过这个时间则自动唤醒。

public class ThreadC9 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC9A threadC9A = new ThreadC9A(obj);
        threadC9A.start();
        while (Thread.activeCount() > 1) {
        }
    }
}
class ThreadC9A extends Thread {
    private Object obj;
    public ThreadC9A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        try {
            synchronized (obj) {
                long startTime = System.currentTimeMillis();
                System.out.println("begin wait,time:[" + startTime + "]");
                obj.wait(5000);
                long endTime = System.currentTimeMillis();
                System.out.println("end wait,time:[" + endTime + "] takes " + (endTime - startTime) + " ms");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:

通过执行结果可以看出,在经过5000ms后,线程被唤醒。

到此这篇关于Java使用wait/notify实现线程间通信下篇的文章就介绍到这了,更多相关Java wait notify内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • nacos配置注册中心时指定命名空间不起作用的问题

    nacos配置注册中心时指定命名空间不起作用的问题

    这篇文章主要介绍了nacos配置注册中心时指定命名空间不起作用的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。
    2022-01-01
  • Java中@Pattern注解常用的校验正则表达式学习笔记

    Java中@Pattern注解常用的校验正则表达式学习笔记

    对于正则这个东西,对我来说一直是很懵逼的,每次用每次查,然后还是记不住,下面这篇文章主要给大家介绍了关于Java中@Pattern注解常用的校验正则表达式学习笔记的相关资料,需要的朋友可以参考下
    2022-07-07
  • SpringBoot JPA懒加载失效的解决方案(亲测有效)

    SpringBoot JPA懒加载失效的解决方案(亲测有效)

    这篇文章主要介绍了SpringBoot JPA懒加载失效的解决方案(亲测有效),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • JDK8环境中使用struts2的步骤详解

    JDK8环境中使用struts2的步骤详解

    这篇文章主要给大家介绍了关于在JDK8环境中使用struts2的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • 详解Java Proxy动态代理机制

    详解Java Proxy动态代理机制

    今天给大家带来的是关于Java的相关知识,文章围绕着Java动态代理机制展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • redis做服务间通信工具的项目示例

    redis做服务间通信工具的项目示例

    Redis是一种高效的服务间通信工具,它以键值对的形式存储数据,并支持多种数据类型和丰富的操作,本文主要介绍了redis做服务间通信工具的项目示例,感兴趣的可以了解一下
    2023-08-08
  • Java 处理高并发负载类优化方法案例详解

    Java 处理高并发负载类优化方法案例详解

    这篇文章主要介绍了Java 处理高并发负载类优化方法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java解析http协议字符串的方法实现

    Java解析http协议字符串的方法实现

    本文主要介绍了Java解析http协议字符串的方法实现,我们探讨了如何使用Java解析HTTP协议字符串,并将其封装成了一个HttpRequest类,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • springboot 如何设置端口号和添加项目名

    springboot 如何设置端口号和添加项目名

    这篇文章主要介绍了springboot设置端口号和添加项目名的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java数组优点和缺点_动力节点Java学院整理

    Java数组优点和缺点_动力节点Java学院整理

    本文给大家简单介绍下java数组的优点和缺点知识,需要的的朋友参考下吧
    2017-04-04

最新评论