📜  Java并发——yield()、sleep() 和 join() 方法(1)

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

Java并发——yield()、sleep() 和 join() 方法

Java中的多线程是实现程序并发的一种方法,它可以使程序在同一时间内执行多个任务。但是,当多个线程共享相同的资源时,就可能会导致冲突和不一致的结果。因此,开发者需要了解如何使用Java并发库来确保线程安全。

Java中提供了一些方法来处理线程之间的协作。yield()、sleep() 和 join() 是这些方法中最常用的三种。这篇文章将会介绍这三种方法及其用法。

yield()方法

yield() 方法是一个静态方法,该方法会使当前正在执行的线程暂停并允许其他可运行线程执行。这个方法的作用是向调度程序提示当前线程愿意让出 CPU 执行时间,但是并不能保证一定会让出 CPU 资源,也不能保证让出的 CPU 资源会被其他线程立即执行。

下面是一个使用 yield() 方法的示例代码:

public class YieldExample implements Runnable {

    String name;

    YieldExample(String name) {
        this.name = name;
    }

    public void run() {

        for (int i = 0; i < 5; i++) {

            // Yield control to another thread
            Thread.yield();

            System.out.println(name + " running");
        }
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new YieldExample("Thread 1"));
        Thread t2 = new Thread(new YieldExample("Thread 2"));

        t1.start();
        t2.start();
}

输出结果:

Thread 1 running
Thread 2 running
Thread 1 running
Thread 2 running
Thread 1 running
Thread 2 running
Thread 1 running
Thread 2 running
Thread 1 running
Thread 2 running

由于使用了 yield() 方法,两个线程轮流执行了5次,而不是一个线程执行完毕后另一个线程再执行。

需要注意的是,yield() 方法不应该被滥用。如果过度使用,它可能会导致 CPU 的利用率减少。

sleep() 方法

sleep() 方法会使当前线程暂停执行指定的时间。该方法的一个常见用途是模拟线程之间的时间间隔,通常结合其他方法使用来使程序的执行更具可控性。

下面是一个使用 sleep() 方法的示例代码:

public class SleepExample implements Runnable {

    String name, message;

    SleepExample(String name, String message) {
        this.name = name;
        this.message = message;
    }

    public void run() {
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + " : " + message);
                Thread.sleep(1000); // sleep for 1 second
            }
        } catch (InterruptedException e) {}
        
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new SleepExample("Thread 1", "Hello"));
        Thread t2 = new Thread(new SleepExample("Thread 2", "World"));

        t1.start();
        t2.start();
    }
}

输出结果:

Thread 1 : Hello
Thread 2 : World
Thread 1 : Hello
Thread 2 : World
Thread 1 : Hello
Thread 2 : World
Thread 1 : Hello
Thread 2 : World
Thread 1 : Hello
Thread 2 : World

在这个例子中,每个线程将执行5次打印操作,在两次打印之间暂停1秒钟。

在使用 sleep() 方法时,需要注意它可能会抛出 InterruptedException 异常,因此需要进行适当的异常处理。

join() 方法

join() 方法用于等待一个线程的执行完成。该方法会阻塞调用 join() 方法的线程,直到被等待的线程执行完成。

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

public class JoinExample implements Runnable {

    String name;

    JoinExample(String name) {
        this.name = name;
    }

    public void run() {
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + " running");
                Thread.sleep(1000); // sleep for 1 second
            }
        } catch (InterruptedException e) {}
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new JoinExample("Thread 1"));
        Thread t2 = new Thread(new JoinExample("Thread 2"));

        t1.start();

        // Wait for t1 to finish
        t1.join();

        t2.start();
    }
}

输出结果:

Thread 1 running
Thread 1 running
Thread 1 running
Thread 1 running
Thread 1 running
Thread 2 running
Thread 2 running
Thread 2 running
Thread 2 running
Thread 2 running

在这个例子中,线程 t2 在执行之前需要等待线程 t1 执行完成。调用 t1.join() 方法使得主线程等待 t1 的执行完成后,才开始启动 t2 线程。

需要注意的是,join() 方法被调用时可以指定等待的时间,例如 t1.join(5000); 会等待 t1 执行完成或过了 5000 毫秒后才会执行后面的代码。如果不指定等待时间,默认会一直等待线程执行完毕。

总结

yield()、sleep() 和 join() 都是 Java 并发库提供的非常有用的方法。使用它们可以帮助我们更好地控制线程的执行,避免冲突和不一致的结果。需要注意的是,这些方法都不是万能的,过度使用它们可能会导致性能下降或其他不良后果。因此,使用它们时需要谨慎。