Java Wait用法

Java中的wait()方法是实现线程同步的重要手段之一,它可以让线程等待其他线程的通知或者到达某个状态再执行,有助于优化程序性能。本文将从多个角度详细介绍Java Wait用法。

一、wait()方法的作用及基本用法

Java中的wait()方法可以让一个线程等待另一个线程发出的通知或者到达某个状态再执行,主要用于实现线程之间的同步和协作。因为Java中的线程是资源共享的,线程之间的访问需要协调和同步,wait()方法就是一种实现线程同步的手段。

wait()方法的基本用法如下:

public synchronized void wait() throws InterruptedException

在synchronized方法中调用wait()方法时,当前线程进入等待状态,直到其他线程调用notify()或者notifyAll()方法通知当前线程,或者等待时间耗尽才结束等待状态。

wait()方法的示例代码:

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " start waiting...");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() + " end waiting...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
            }
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述示例代码中,thread1线程调用了wait()方法,进入等待状态,直到thread2线程调用了notify()方法之后,才结束等待状态。

二、wait()方法与notify()方法的配对使用

在使用wait()方法时,需要与notify()方法配对使用,notify()方法可以唤醒等待状态的线程,让它重新开始执行。

notify()方法的基本用法如下:

public final native void notify()

notify()方法的典型用法如下:

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " start waiting...");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() + " end waiting...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
            }
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述示例中,thread1线程调用了wait()方法进入等待状态,直到thread2线程调用了notify()方法唤醒thread1线程,thread1线程才结束等待状态并重新执行。

三、wait()方法和notify()方法的注意事项

1. wait()方法和notify()方法只能在synchronized代码块中使用

由于wait()方法和notify()方法需要对共享变量进行操作,因此只能在synchronized代码块中使用,否则会抛出IllegalMonitorStateException异常。

下面是一个使用wait()方法和notify()方法的非法示例:

public class ThreadTest {
    private static Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread2 = new Thread(() -> {
            lock.notify();
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述代码中,wait()方法和notify()方法不在synchronized代码块中使用,因此会抛出IllegalMonitorStateException异常。

2. wait()方法必须放在循环中使用

在使用wait()方法时,为了避免虚假唤醒问题(即线程没有收到notify()通知,但是等待结束了),wait()方法必须放在循环中使用,如下所示:

public class ThreadTest {
    private static Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " start waiting...");
                        lock.wait();
                        System.out.println(Thread.currentThread().getName() + " end waiting...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
            }
        });
        thread1.start();
        Thread.sleep(1000);//等待线程1进入wait状态
        thread2.start();
    }
}

上述代码中,wait()方法放在while循环中使用,当线程被虚假唤醒时,会重新进入循环,直到收到notify()通知才结束等待状态。

3. notify()方法不会释放锁

在调用notify()方法时,不会释放锁,因此在执行完notify()方法之后,线程仍然会保持锁定状态,在synchronized代码块中继续执行。

下面是一个示例代码:

public class ThreadTest {
    private static Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " start waiting...");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() + " end waiting...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
                System.out.println(Thread.currentThread().getName() + " do something after notify...");
            }
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述代码中,当thread2线程调用notify()方法时,仅仅唤醒了thread1线程,而不会释放锁,因此thread2线程在执行完notify()方法之后,仍然在synchronized代码块中执行,直到执行完毕后才释放锁。

四、wait()方法的其他用法

除了基本用法外,wait()方法还可以通过指定等待时间或者超时时间,来控制等待状态的结束,具体如下:

1. 指定等待时间

wait()方法可以指定等待时间,单位为毫秒,如果在指定时间内,其他线程没有调用notify()方法通知当前线程,那么当前线程会自动结束等待状态,继续向下执行。

wait()方法的用法如下:

public synchronized void wait(long timeout) throws InterruptedException
public final native void wait(long timeout, int nanos) throws InterruptedException

示例代码如下:

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " start waiting for 2 seconds...");
                    lock.wait(2000);
                    System.out.println(Thread.currentThread().getName() + " end waiting...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
            }
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述示例中,thread1线程调用了wait(2000)方法,等待2秒后自动结束等待状态执行,即使此时还没有收到notify()通知。

2. 超时时间

wait()方法还可以通过指定超时时间来控制等待状态的结束,单位为纳秒,如果在指定时间内,其他线程没有调用notify()方法通知当前线程,那么当前线程会自动结束等待状态,继续向下执行。

wait()方法的用法如下:

public final native void wait(long timeout, int nanos) throws InterruptedException

示例代码如下:

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " start waiting...");
                    long start = System.nanoTime();
                    lock.wait(1000, 500);
                    long end = System.nanoTime();
                    System.out.println(Thread.currentThread().getName() + " end waiting..., elapsed time: " + (end - start) + "ns");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " notify...");
                lock.notify();
            }
        });
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

上述示例中,thread1线程调用了wait(1000, 500)方法,等待1秒500纳秒后自动结束等待状态执行,即使此时还没有收到notify()通知。

五、总结

本文从wait()方法的作用及基本用法、wait()方法与notify()方法的配对使用、wait()方法和notify()方法的注意事项、wait()方法的其他用法等多个方面对Java Wait用法做了详细的阐述,并给出了相应的示例代码,希望能够帮助读者深入理解Java Wait用法的实现原理和使用方法。

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
JMPCJMPC
上一篇 2024-10-04 00:24
下一篇 2024-10-04 00:24

相关推荐

  • Java JsonPath 效率优化指南

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

    编程 2025-04-29
  • java client.getacsresponse 编译报错解决方法

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

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

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

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

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

    编程 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

发表回复

登录后才能评论