📜  java 等待 - Java (1)

📅  最后修改于: 2023-12-03 15:01:34.451000             🧑  作者: Mango

Java等待

在Java中,我们可以使用等待(wait)方法来阻塞一个线程,直到某个条件得到满足。等待通常用于多线程情况下进行同步。

使用wait方法

等待方法只能在同步代码块(或同步方法)中调用,它会导致当前线程进入等待状态,并释放锁。等待状态将持续到另一个线程持有相同对象的锁,并通知正在等待的线程调用notify()或notifyAll()方法。

方法声明

wait方法有两个重载方法:

public final void wait() throws InterruptedException

public final native void wait(long timeout) throws InterruptedException

第一个方法使当前线程一直等待,直到另一个线程调用notify()或notifyAll()方法;第二个方法允许你指定最长等待时间。

使用示例
public class WaitExample {
    public synchronized void waitForSignal() throws InterruptedException {
        wait();
    }

    public synchronized void doNotify() {
        notify();
    }
}

在这个示例中,我们声明了一个waitForSignal()方法,用于等待另一个线程调用doNotify()方法。注意,这两个方法都是同步的。

使用示例:

WaitExample example = new WaitExample();

new Thread(() -> {
    try {
        example.waitForSignal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

Thread.sleep(1000);  // 模拟一些处理时间

example.doNotify();

这里我们创建了一个WaitExample对象,并使用一个线程调用waitForSignal()方法,此时线程将进入等待状态。然后我们暂停主线程一段时间,之后调用doNotify()方法,这将使waitForSignal()方法继续执行。

使用join方法

另一种等待线程结束的方法是使用join()方法。join()方法会阻塞当前线程,直到被调用线程结束。

方法声明

join()方法有三个重载方法:

public final void join() throws InterruptedException

public final synchronized void join(long millis) throws InterruptedException

public final synchronized void join(long millis, int nanos) throws InterruptedException

第一个方法会一直等待,直到被调用线程结束。另外两个方法允许你指定最长等待时间。

使用示例
Thread t = new Thread(() -> {
    // 模拟一些处理时间
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

t.start();
t.join();

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

这里我们创建了一个线程t,并使用join()方法阻塞主线程,直到t线程执行完毕。注意,这个示例没有使用同步代码,因为我们只是等待一个简单的线程完成。

使用CountDownLatch类

CountDownLatch类可以用于等待一组线程完成。当我们想要等待多个线程完成时,使用这个类比使用join()方法更加实用。

类定义

CountDownLatch类是一个同步辅助类,它的构造方法接收一个正整数参数作为初始化计数器的值,表示需要等待的线程数量。每个线程完成任务后,都会调用countDown()方法使计数器减1。当计数器减到0时,所有等待线程会被唤醒。

public class CountDownLatch {
    public CountDownLatch(int count) { ... }

    public void await() throws InterruptedException { ... }

    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { ... }

    public void countDown() { ... }

    public long getCount() { ... }
}
使用示例
CountDownLatch latch = new CountDownLatch(5);

for (int i = 0; i < 5; i++) {
    new Thread(() -> {
        // 模拟一些处理时间
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        latch.countDown();
    }).start();
}

latch.await();

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

在这个示例中,我们创建了一个CountDownLatch对象,并初始化计数器为5。然后创建了5个线程,每个线程都会调用latch.countDown()方法以使计数器减1。最后我们调用latch.await()方法等待所有线程完成。

总结

在Java中,我们可以使用等待方法、join()方法、CountDownLatch类等方式来等待线程完成。使用等待方法可以用于多线程同步,使用join()方法可以等待单个线程完成,使用CountDownLatch类可以等待一组线程完成。要注意等待方法只能在同步代码块中调用,并需要在另一个线程调用notify()或notifyAll()方法来唤醒等待线程。