确保Java多线程按顺序执行的几种方法

Answered using GPT-4o-mini by Java Q&A Hub

Question:

Java面试题之多线程 有三个线程T1,T2,T3,怎么确保它们按顺序执行?

Answer:

在Java中,可以使用多种方法来确保多个线程按特定顺序执行。以下是几种常见的方法:

1. 使用 join() 方法

可以通过调用线程的 join() 方法来确保一个线程在另一个线程完成后再执行。

class Task implements Runnable {
    private String name;

    public Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + " is running.");
    }
}

public class ThreadOrder {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Task("T1"));
        Thread t2 = new Thread(new Task("T2"));
        Thread t3 = new Thread(new Task("T3"));

        t1.start();
        t1.join(); // 等待 t1 完成

        t2.start();
        t2.join(); // 等待 t2 完成

        t3.start();
        t3.join(); // 等待 t3 完成
    }
}

2. 使用 CountDownLatch

CountDownLatch 是一个同步辅助类,可以用来让一个或多个线程等待直到在其他线程中执行的一组操作完成。

import java.util.concurrent.CountDownLatch;

class Task implements Runnable {
    private String name;
    private CountDownLatch latch;

    public Task(String name, CountDownLatch latch) {
        this.name = name;
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out.println(name + " is running.");
        latch.countDown(); // 完成任务,计数减一
    }
}

public class ThreadOrder {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch1 = new CountDownLatch(1);
        CountDownLatch latch2 = new CountDownLatch(1);

        Thread t1 = new Thread(new Task("T1", latch1));
        Thread t2 = new Thread(new Task("T2", latch2));
        Thread t3 = new Thread(new Task("T3", null));

        t1.start();
        latch1.await(); // 等待 t1 完成

        t2.start();
        latch2.await(); // 等待 t2 完成

        t3.start();
    }
}

3. 使用 Semaphore

Semaphore 也可以用来控制线程的执行顺序。

import java.util.concurrent.Semaphore;

class Task implements Runnable {
    private String name;
    private Semaphore semaphore;

    public Task(String name, Semaphore semaphore) {
        this.name = name;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire(); // 获取许可
            System.out.println(name + " is running.");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release(); // 释放许可
        }
    }
}

public class ThreadOrder {
    public static void main(String[] args) {
        Semaphore semaphore1 = new Semaphore(1);
        Semaphore semaphore2 = new Semaphore(0);

        Thread t1 = new Thread(new Task("T1", semaphore1));
        Thread t2 = new Thread(new Task("T2", semaphore2));
        Thread t3 = new Thread(new Task("T3", semaphore2));

        t1.start();
        t2.start();
        t3.start();

        // 先释放 T1 的许可
        semaphore1.release();
        // 然后释放 T2 的许可
        semaphore2.release();
    }
}

4. 使用 ExecutorServiceFuture

可以使用 ExecutorService 来提交任务,并通过 Future 来控制任务的执行顺序。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class Task implements Runnable {
    private String name;

    public Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + " is running.");
    }
}

public class ThreadOrder {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        Future<?> future1 = executor.submit(new Task("T1"));
        future1.get(); // 等待 T1 完成

        Future<?> future2 = executor.submit(new Task("T2"));
        future2.get(); // 等待 T2 完成

        Future<?> future3 = executor.submit(new Task("T3"));
        future3.get(); // 等待 T3 完成

        executor.shutdown();
    }
}

以上是几种确保线程按顺序执行的方法。根据具体的需求和场景,可以选择合适的方式来实现。