前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >面试官:保证线程顺序执行的方法

面试官:保证线程顺序执行的方法

作者头像
用户11397231
发布2025-01-24 10:43:50
发布2025-01-24 10:43:50
4500
代码可运行
举报
文章被收录于专栏:算法算法
运行总次数:0
代码可运行

保证线程顺序执行的方法

考察意图

在面试中出现这道问题,通常是为了考察候选人的以下几个知识点:

  1. 多线程基础知识:了解候选人是否熟悉 Java 多线程的基本概念,包括线程的创建、启动和同步机制。
  2. 同步机制的理解:候选人需要展示对 Java 中各种同步工具的理解,如 join()CountDownLatchSemaphoreCyclicBarrier 等,并知道如何在不同场景下应用这些工具。
  3. 线程间通信:希望候选人理解线程间通信的基本原理,例如如何使用 wait()notify() 来协调线程。
  4. 对 Java 并发包的熟悉程度:希望候选人了解 Java 并发包(java.util.concurrent)中的工具和类,展示其对现代 Java 并发编程的掌握。

保证线程顺序执行的方法

1. 使用 join()

join() 方法是 Thread 类的一部分,可以让一个线程等待另一个线程完成执行。当你在一个线程 T 上调用 T.join() 时,调用线程将进入等待状态,直到线程 T 完成(即终止)。因此,可以通过在每个线程启动后调用 join() 来实现顺序执行。

示例代码

代码语言:javascript
代码运行次数:0
复制
Thread t1 = new Thread(() -> {
    // 线程 T1 的任务
    System.out.println("T1 执行");
});

Thread t2 = new Thread(() -> {
    // 线程 T2 的任务
    System.out.println("T2 执行");
});

Thread t3 = new Thread(() -> {
    // 线程 T3 的任务
    System.out.println("T3 执行");
});

t1.start();
try {
    t1.join(); // 等待 T1 完成
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

t2.start();
try {
    t2.join(); // 等待 T2 完成
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

t3.start();
try {
    t3.join(); // 等待 T3 完成
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
2. 使用 CountDownLatch

CountDownLatch 通过一个计数器来实现,初始时,计数器的值由构造函数设置,每次调用 countDown() 方法,计数器的值减 1。当计数器的值变为零时,所有等待在 await() 方法上的线程都将被唤醒,继续执行。

示例代码

代码语言:javascript
代码运行次数:0
复制
CountDownLatch latch1 = new CountDownLatch(1);
CountDownLatch latch2 = new CountDownLatch(1);

Thread t1 = new Thread(() -> {
    // 线程 T1 的任务
    System.out.println("T1 执行");
    latch1.countDown(); // 完成后递减 latch1
});

Thread t2 = new Thread(() -> {
    try {
        latch1.await(); // 等待 T1 完成
        // 线程 T2 的任务
        System.out.println("T2 执行");
        latch2.countDown(); // 完成后递减 latch2
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

Thread t3 = new Thread(() -> {
    try {
        latch2.await(); // 等待 T2 完成
        // 线程 T3 的任务
        System.out.println("T3 执行");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

t1.start();
t2.start();
t3.start();
3. 使用 Semaphore

Semaphore 通过一个计数器来管理许可,计数器的初始值由构造函数指定,表示可用许可的数量。线程可以通过调用 acquire() 方法请求许可,如果许可可用则授予访问权限,否则线程将阻塞。使用完资源后,线程调用 release() 方法释放许可,从而允许其他阻塞的线程获取许可。

示例代码

代码语言:javascript
代码运行次数:0
复制
Semaphore semaphore1 = new Semaphore(0);
Semaphore semaphore2 = new Semaphore(0);

Thread t1 = new Thread(() -> {
    // 线程 T1 的任务
    System.out.println("T1 执行");
    semaphore1.release(); // 释放一个许可
});

Thread t2 = new Thread(() -> {
    try {
        semaphore1.acquire(); // 获取许可,等待 T1 完成
        // 线程 T2 的任务
        System.out.println("T2 执行");
        semaphore2.release(); // 释放一个许可
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

Thread t3 = new Thread(() -> {
    try {
        semaphore2.acquire(); // 获取许可,等待 T2 完成
        // 线程 T3 的任务
        System.out.println("T3 执行");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

t1.start();
t2.start();
t3.start();
4. 使用单线程池

单线程池(Executors.newSingleThreadExecutor())可以确保任务按提交顺序依次执行。所有任务都会在同一个线程中运行,保证了顺序性。

示例代码

代码语言:javascript
代码运行次数:0
复制
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
    // 线程 T1 的任务
    System.out.println("T1 执行");
});
executor.submit(() -> {
    // 线程 T2 的任务
    System.out.println("T2 执行");
});
executor.submit(() -> {
    // 线程 T3 的任务
    System.out.println("T3 执行");
});
executor.shutdown();
5. 使用 synchronized

synchronized 是 Java 中的一个关键字,用于实现线程同步,确保多个线程对共享资源的访问是互斥的。它通过锁机制来保证同一时刻只有一个线程可以执行被 synchronized 保护的代码块,从而避免数据不一致和线程安全问题。

示例代码

代码语言:javascript
代码运行次数:0
复制
class Task {
    synchronized void executeTask(String taskName) {
        System.out.println(taskName + " 执行");
    }
}

public class Main {
    public static void main(String[] args) {
        Task task = new Task();
        new Thread(() -> task.executeTask("T1")).start();
        new Thread(() -> task.executeTask("T2")).start();
        new Thread(() -> task.executeTask("T3")).start();
    }
}
6. 使用 CompletableFuture

CompletableFuture 是 Java 8 引入的类,属于 java.util.concurrent 包。它是一个功能强大的工具,用于处理异步编程。CompletableFuture 允许创建、操作和组合任务,可以说是处理异步任务的一个灵活和强大的解决方案。

示例代码

代码语言:javascript
代码运行次数:0
复制
import java.util.concurrent.CompletableFuture;

public class CompletableFutureSequentialExecution {

    public static void main(String[] args) {
        // 创建第一个任务 T1
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("T1 is running on thread: " + Thread.currentThread().getName());
            // 模拟任务运行
            sleep(1000);
        });
        
        // 链接任务 T2 到 T1 之后
        future = future.thenRunAsync(() -> {
            System.out.println("T2 is running on thread: " + Thread.currentThread().getName());
            sleep(1000);
        });

        // 链接任务 T3 到 T2 之后
        future = future.thenRunAsync(() -> {
            System.out.println("T3 is running on thread: " + Thread.currentThread().getName());
            sleep(1000);
        });

        // 等待所有任务完成
        future.join();
    }

    // 辅助方法用于模拟延迟
    private static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

总结

本文介绍了 6 种保证线程 T1、T2 和 T3 顺序执行的方法,依次如下:

  1. 使用 join():通过 join() 方法让一个线程等待另一个线程完成。
  2. 使用 CountDownLatch:通过计数器实现线程的顺序执行。
  3. 使用 Semaphore:通过许可管理实现线程的顺序执行。
  4. 使用单线程池:通过单线程池确保任务按提交顺序依次执行。
  5. 使用 synchronized:通过锁机制确保线程同步。
  6. 使用 CompletableFuture:通过异步任务的链式调用实现顺序执行。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 保证线程顺序执行的方法
    • 考察意图
    • 保证线程顺序执行的方法
      • 1. 使用 join()
      • 2. 使用 CountDownLatch
      • 3. 使用 Semaphore
      • 4. 使用单线程池
      • 5. 使用 synchronized
      • 6. 使用 CompletableFuture
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档