Java中notify()的使用

在Java中,线程同步与互斥是非常重要的概念。以往我们使用synchronized关键字来锁定某个方法或某段代码块,以保持线程的同步与互斥。在这篇文章中,我们将介绍另一个重要的关键字——notify()。notify()方法的作用是唤醒等待线程队列中的某个线程,并将该线程移动到锁池中。对于正在运行的线程,notify()方法不会产生任何影响。如果你想在某个时刻唤醒一个等待线程,你需要在代码中仔细地实现它。

一、notify()方法的使用

我们将具体了解notify()方法的使用。notify()方法要在synchronized块中调用,以确保该对象的锁定机制。

public class NotifyTest {
     public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        
        synchronized(b) {
            try {
                System.out.println("Waiting for b to complete...");
                b.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            System.out.println("Total is: " + b.total);
        }
     }
}

class ThreadB extends Thread {
    int total;
    
    public void run() {
        synchronized(this) {
            for(int i=0; i<100 ; i++) {
                total += i;
            }
            notify();
        }
    }
}

在这个例子中,我们创建了两个线程:一个线程是主线程,另一个线程是ThreadB。main线程在运行时,调用synchronized方法锁定ThreadB对象。然后,main线程调用ThreadB.wait()方法来等待ThreadB线程的完成。在ThreadB线程完成之后,total的值会被打印出来。

二、notify()方法的限制

notify()方法除了唤醒等待线程之外,它并没有其他的效果。如果一个线程被notify()唤醒,它不会立即执行。相反,该线程需要重新进入该对象的锁池并等待重新获得该对象的锁,然后才能继续执行。

还有一个限制是,notify()方法只会唤醒等待队列中的其中一个线程,并且我们不能指定哪个线程会被唤醒。也就是说,我们无法控制具体唤醒哪一个等待线程。

三、notifyAll()方法的使用

我们介绍了notify()方法的基本使用和限制,现在我们将介绍另一个方法:notifyAll()。notifyAll()方法唤醒等待队列中的所有线程。

public class NotifyAllTest {
    public static void main(String[] args) {
        Message msg = new Message("process it");
        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1,"waiter1").start();
        
        Waiter waiter2 = new Waiter(msg);
        new Thread(waiter2, "waiter2").start();
        
        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("All threads started");
    }
}

class Message {
    private String msg;

    public Message(String str){
        this.msg=str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg=str;
    }
}

class Waiter implements Runnable{
    private Message msg;

    public Waiter(Message m){
        this.msg=m;
    }

    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (msg) {
            try{
                System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
            //process the message now
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }
}

class Notifier implements Runnable {
    private Message msg;

    public Notifier(Message msg) {
        this.msg = msg;
    }

    public void run() {
        Thread.currentThread().setName("notifier");
        System.out.println("Started notifying at time:"+System.currentTimeMillis());
        synchronized (msg) {
            msg.setMsg("Notifying all waiting threads");
            msg.notifyAll();
            // msg.notify();
        }
    }
}

在这个例子中,我们创建了一个Message类,一个Waiter类和一个Notifier类。Waiter类等待Notifier类的通知,Notifier类发出通知,等待的Waiter类会被唤醒并继续执行。

在这个例子中,我们使用了wait()和notifyAll()方法。wait()方法可将当前线程放入对象的等待队列中,并释放对象锁,以便其他线程可以获得该对象的锁并继续执行。notifyAll()方法将唤醒所有正在等待该对象的线程,这些线程将重新进入对象的锁池,并准备重新获得对象的锁。

四、总结

在本篇文章中,我们介绍了Java中notify()方法的基本使用和限制,以及notifyAll()方法的使用。notify()方法是唤醒等待队列中的某个线程,notifyAll()方法是唤醒等待队列中的所有线程。在使用notify()和notifyAll()方法时,需要确保已经获得对象锁,以便它可以执行正确的操作。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/193898.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-02 09:41
下一篇 2024-12-02 09:41

相关推荐

  • java client.getacsresponse 编译报错解决方法

    java client.getacsresponse 编译报错是Java编程过程中常见的错误,常见的原因是代码的语法错误、类库依赖问题和编译环境的配置问题。下面将从多个方面进行分析…

    编程 2025-04-29
  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • Java腾讯云音视频对接

    本文旨在从多个方面详细阐述Java腾讯云音视频对接,提供完整的代码示例。 一、腾讯云音视频介绍 腾讯云音视频服务(Cloud Tencent Real-Time Communica…

    编程 2025-04-29
  • Java Bean加载过程

    Java Bean加载过程涉及到类加载器、反射机制和Java虚拟机的执行过程。在本文中,将从这三个方面详细阐述Java Bean加载的过程。 一、类加载器 类加载器是Java虚拟机…

    编程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介绍

    本文将详细介绍Java Milvus SearchParam withoutFields的相关知识和用法。 一、什么是Java Milvus SearchParam without…

    编程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java语言中的一个版本,于2014年3月18日发布。本文将从多个方面对Java 8中某一周的周一进行详细的阐述。 一、数组处理 Java 8新特性之一是Stream…

    编程 2025-04-29
  • Java判断字符串是否存在多个

    本文将从以下几个方面详细阐述如何使用Java判断一个字符串中是否存在多个指定字符: 一、字符串遍历 字符串是Java编程中非常重要的一种数据类型。要判断字符串中是否存在多个指定字符…

    编程 2025-04-29
  • VSCode为什么无法运行Java

    解答:VSCode无法运行Java是因为默认情况下,VSCode并没有集成Java运行环境,需要手动添加Java运行环境或安装相关插件才能实现Java代码的编写、调试和运行。 一、…

    编程 2025-04-29
  • Java任务下发回滚系统的设计与实现

    本文将介绍一个Java任务下发回滚系统的设计与实现。该系统可以用于执行复杂的任务,包括可回滚的任务,及时恢复任务失败前的状态。系统使用Java语言进行开发,可以支持多种类型的任务。…

    编程 2025-04-29
  • Java 8 Group By 会影响排序吗?

    是的,Java 8中的Group By会对排序产生影响。本文将从多个方面探讨Group By对排序的影响。 一、Group By的概述 Group By是SQL中的一种常见操作,它…

    编程 2025-04-29

发表回复

登录后才能评论