Java线程等待

Java中线程等待是指让一个线程等待其它线程完成一定的工作后再执行。Java提供了几种方式来实现线程等待,包括使用join()方法、wait()和notify()方法、CountDownLatch类、CyclicBarrier类等。本文将会详细介绍这些方法的使用方法和实例。

一、使用join()方法进行线程等待

join()方法是Thread类提供的一个实例方法,它允许一个线程等待另一个线程的完成。当调用某个线程的join()方法时,当前线程会暂停执行,直到被调用线程执行完毕,当前线程才会继续执行。如果被调用线程在join()方法调用前已经执行完毕,那么该方法会立即返回。

下面是一个使用join()方法的示例:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("子线程开始执行");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程执行完毕");
    }
});

thread.start();

System.out.println("主线程开始执行");

try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("主线程执行完毕");

在上述示例中,我们创建了一个新的线程,该线程会等待5秒后执行完毕。在主线程中,我们调用了thread.join()方法,因此主线程会等待子线程执行完毕后再继续执行。输出结果如下:

主线程开始执行
子线程开始执行
子线程执行完毕
主线程执行完毕

二、使用wait()和notify()方法进行线程等待

wait()和notify()方法是Object类提供的实例方法,它们可以实现线程间的等待和唤醒。当一个线程执行wait()方法时,它会释放它所持有的锁,并进入等待状态,直到其它线程调用notify()方法或notifyAll()方法来唤醒它。当一个线程执行notify()方法时,它会唤醒一个正处于等待状态中的线程(注意是随机唤醒一个线程),使其继续执行。

下面是一个使用wait()和notify()方法的示例,该示例演示了如何使用两个线程交替输出1到10:

class PrintThread implements Runnable {
    private int num;
    private Object lock;

    public PrintThread(int num, Object lock) {
        this.num = num;
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + " " + num * 10 + i);
                lock.notify();
                if (i != 9) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

public static void main(String[] args) {
    Object lock = new Object();
    Thread thread1 = new Thread(new PrintThread(1, lock));
    Thread thread2 = new Thread(new PrintThread(2, lock));
    thread1.start();
    thread2.start();
}

在上述示例中,我们创建了两个线程,分别输出1到10和11到20。在PrintThread类的run()方法中,我们首先获取lock对象的锁,并使用wait()方法使线程进入等待状态,直到另一个线程调用notify()方法来唤醒它。当一个线程输出完一行后,使用notify()方法唤醒等待状态的线程,然后自己进入等待状态,等待其它线程唤醒。这样,我们就实现了两个线程交替输出1到20。

三、使用CountDownLatch类进行线程等待

CountDownLatch类是在Java 5中引入的,并且它是java.util.concurrent包中的一个类。它是一个同步的辅助类,用来协调多个线程之间的同步。CountDownLatch的功能是阻塞一个线程或多个线程,直到它所计数的线程执行完毕才能向下执行。它使用一个计数器来实现这个功能,计数器初始值为线程数,当某个线程执行完毕时,计数器减1,当计数器减为0时,所有等待该计数器的线程将会被唤醒。

下面是一个使用CountDownLatch类的示例:

public static void main(String[] args) throws InterruptedException {
    int threadCount = 10;
    CountDownLatch latch = new CountDownLatch(threadCount);

    for (int i = 0; i  {
            System.out.println(Thread.currentThread().getName() + " 执行完毕");
            latch.countDown();
        }).start();
    }

    latch.await();

    System.out.println("所有线程执行完毕");
}

在上述示例中,我们使用了一个CountDownLatch对象来等待10个线程执行完毕。当一个线程执行完毕时,我们调用latch.countDown()方法来减少计数器的值,当计数器减为0时,主线程调用latch.await()方法进入等待状态,直到所有线程执行完毕,主线程才会继续执行。输出结果如下:

Thread-0 执行完毕
Thread-1 执行完毕
Thread-3 执行完毕
Thread-2 执行完毕
Thread-4 执行完毕
Thread-8 执行完毕
Thread-9 执行完毕
Thread-5 执行完毕
Thread-7 执行完毕
Thread-6 执行完毕
所有线程执行完毕

四、使用CyclicBarrier类进行线程等待

CyclicBarrier类也是在Java 5中引入的,它也是java.util.concurrent包中的一个类。CyclicBarrier可以被用来协调多个线程之间的同步。它可以让一组线程在到达某个屏障时被阻塞,直到最后一个线程到达屏障时,所有被阻塞的线程才能继续执行。CyclicBarrier和CountDownLatch的区别在于,CyclicBarrier可以用于一组线程间相互等待,而CountDownLatch只能用于一个线程等待其它线程执行完毕。

下面是一个使用CyclicBarrier类的示例:

class WorkerThread implements Runnable {
    private String name;
    private CyclicBarrier barrier;

    public WorkerThread(String name, CyclicBarrier barrier) {
        this.name = name;
        this.barrier = barrier;
    }

    @Override
    public void run() {
        try {
            System.out.println(name + " 开始工作");
            Thread.sleep((long) (Math.random() * 5000));
            System.out.println(name + " 工作完毕,等待其它线程");
            barrier.await();
            System.out.println(name + " 继续执行");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) throws InterruptedException {
    int threadCount = 5;
    CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
        System.out.println("所有线程工作完毕,开始汇总结果");
    });

    for (int i = 0; i < threadCount; i++) {
        new Thread(new WorkerThread("线程" + i, barrier)).start();
    }

    Thread.sleep(6000);
}

在上述示例中,我们创建了5个线程,它们会随机工作一段时间后等待其它线程,最后再汇总工作结果。在WorkerThread类的run()方法中,我们使用CyclicBarrier类的await()方法来等待其它线程,当所有线程都到达屏障时,所有线程才能继续执行。输出结果如下:

线程0 开始工作
线程2 开始工作
线程4 开始工作
线程3 开始工作
线程1 开始工作
线程2 工作完毕,等待其它线程
线程0 工作完毕,等待其它线程
线程1 工作完毕,等待其它线程
线程3 工作完毕,等待其它线程
线程4 工作完毕,等待其它线程
所有线程工作完毕,开始汇总结果
线程4 继续执行
线程1 继续执行
线程0 继续执行
线程2 继续执行
线程3 继续执行

总结

Java中提供了多种方法来实现线程等待,包括使用join()方法、wait()和notify()方法、CountDownLatch类、CyclicBarrier类等。在实际代码编写中,我们需要根据具体的需求选择合适的方式来实现线程等待。无论是哪种方式,它们都可以帮助我们实现线程之间的同步,保证多个线程之间的协作。

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-16 13:36
下一篇 2024-12-16 13:36

相关推荐

  • 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

发表回复

登录后才能评论