Android,Java,Kotlin 确保线程顺序执行的多种实现方式

在多线程编程中,有时需要确保一个线程必须等待另一个线程执行完毕后再执行。本文将介绍几种常见的方法来实现这一需求,并提供详细的代码示例。

1. 使用 Thread.join()
Thread.join() 是最简单直接的方法,它会让当前线程等待目标线程执行完毕。

代码示例:

复制代码
Thread thread1 = new Thread(() -> {
    System.out.println("线程1执行");
});

Thread thread2 = new Thread(() -> {
    try {
        thread1.join(); // 等待线程1执行完毕
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("线程2执行");
});

thread1.start();
thread2.start();

2. 使用 CountDownLatch
CountDownLatch 是一个同步工具,可以让线程等待其他线程完成。通过 countDown() 和 await() 方法实现线程间的同步。

代码示例:

复制代码
CountDownLatch latch = new CountDownLatch(1);

Thread thread1 = new Thread(() -> {
    System.out.println("线程1执行");
    latch.countDown(); // 通知线程2可以执行
});

Thread thread2 = new Thread(() -> {
    try {
        latch.await(); // 等待线程1执行完毕
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("线程2执行");
});

thread1.start();
thread2.start();

3. 使用 ExecutorService 和单线程池

通过 Executors.newSingleThreadExecutor() 创建单线程池,任务会按提交顺序执行,确保线程2在线程1之后执行。

代码示例:

复制代码
ExecutorService executor = Executors.newSingleThreadExecutor();

executor.submit(() -> {
    System.out.println("线程1执行");
});

executor.submit(() -> {
    System.out.println("线程2执行");
});

executor.shutdown(); // 关闭线程池

4. 使用 CompletableFuture
CompletableFuture 是 Java 8 引入的异步编程工具,可以方便地实现任务依赖。

代码示例:

复制代码
CompletableFuture.runAsync(() -> {
    System.out.println("线程1执行");
}).thenRun(() -> {
    System.out.println("线程2执行");
}).join(); // 等待所有任务完成

5. 使用 HandlerThread
HandlerThread 是 Android 中带有 Looper 的线程,可以按顺序处理任务。

代码示例:

复制代码
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();

Handler handler = new Handler(handlerThread.getLooper());

handler.post(() -> {
    System.out.println("线程1执行");
});

handler.post(() -> {
    System.out.println("线程2执行");
});

6. 使用 BlockingQueue
BlockingQueue 是一个线程安全的队列,可以用来实现任务的有序执行。

代码示例:

复制代码
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

Thread thread1 = new Thread(() -> {
    System.out.println("线程1执行");
    queue.offer(() -> System.out.println("线程2执行")); // 将任务2放入队列
});

Thread thread2 = new Thread(() -> {
    try {
        Runnable task = queue.take(); // 等待任务2
        task.run();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

thread1.start();
thread2.start();

7. 使用 Kotlin 协程

如果使用 Kotlin,协程是最简洁的方式,可以轻松实现线程间的依赖关系。

代码示例:

复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        println("线程1执行")
    }.join() // 等待线程1执行完毕

    launch {
        println("线程2执行")
    }
}

以下是几种常见方法的对比:

方法 适用场景 优点 缺点
Thread.join() 简单场景 代码简单 不适合复杂场景

CountDownLatch 需要明确同步点的场景 灵活性强 需要额外管理计数器

单线程池 任务队列场景 代码简洁 需要手动关闭线程池

CompletableFuture Java 8+ 的异步编程 现代化,功能强大 需要 Java 8+ 支持

HandlerThread Android 环境 适合 Android 开发 仅适用于 Android

BlockingQueue 需要任务队列的场景 线程安全,灵活 代码稍复杂

Kotlin 协程 Kotlin 项目 代码简洁,现代化 仅适用于 Kotlin

根据具体需求选择最适合的方案。如果只是简单的线程等待,推荐使用 Thread.join() 或 CountDownLatch;如果是 Android 开发,推荐使用 HandlerThread 或 Kotlin 协程。

相关推荐
geovindu几秒前
java: Strategy Pattern
java·开发语言·后端·设计模式·策略模式·行为模式
yimindev7 分钟前
从 BI 到 Agent:我如何用 Java 打造一个轻量级数据库语义网关 DatI
java
计算机毕设定制辅导-无忧学长9 分钟前
《基于SpringBoot的家政服务管理平台的设计与实现》
java·vue.js·spring boot·计算机毕业设计选题推荐·家政服务管理平台
秋饼10 分钟前
Spring AI 2.0 企业级文档ETL实战:从 DocumentReader 到 EmbeddingStore 的完整知识库数据管道
java·ai·技术分享·后端开发
吃饱了得干活13 分钟前
Spring Boot + Redis 分布式锁:一个订单重复提交引发的六次迭代
java·redis·后端
xiaoqiMikko15 分钟前
pom 里没有、代码里没调过,但 WebClient 默认用的就是 netty-resolver-dns
java·spring boot
wuminyu16 分钟前
Kafka的写入延迟与磁盘IO抖动原理分析
java·linux·c语言·jvm·c++
aramae24 分钟前
模拟实现strcpy(字符串拷贝)(C语言)
java·c语言·开发语言·算法
IT毕设实战小研32 分钟前
基于大数据的跨国外派人员适应满意度与留存影响因素可视化分析
android·java·大数据·python·django·课程设计
letisgo535 分钟前
JAVA 高级进阶10篇《消息队列实战:RocketMQ/Kafka选型与“不丢不重有序“三连解》
java·面试·kafka·消息队列·rocketmq