三个线程 a、b、c 并发运行,b,c 需要 a 线程的数据如何解决

发布于:2025-05-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

说明: 开发中经常会碰到线程并发,但是后续线程需要等待第一个线程执行完返回结果后,才能再执行后面线程。
如何处理呢,今天就介绍两种方法

1、使用Java自有的API即CountDownLatch,进行实现

思考:CountDownLatch通过一个计数器来实现线程等待,计数器初始化为需要等待的事件数量。在这里,线程a完成后,b和c才能继续,所以计数器应该是1。当a完成数据准备后,调用countDown(),计数器减到0,这时候等待的b和c就可以继续执行了。

public class CountDownLatchDemo {
    // 定义共享数据(确保可见性,使用 volatile)
    private static volatile String data;
    // 初始化 CountDownLatch,计数器为 1(只需要等待线程 a 完成一次操作)
    private static final CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) {

        // 启动线程 a、b、c
        new Thread(new Runnable() {
            public void run() {
                threadC();
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                threadB();
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                threadA();
            }
        }).start();
    }

    // 线程 a:准备数据
    private static void threadA() {
        try {
            // 模拟耗时操作(如计算、IO)
            Thread.sleep(1000);
            data = "来自线程 A 的数据";
            System.out.println("线程 A 数据准备完毕");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 数据就绪后,释放计数器
            latch.countDown();
        }
    }

    // 线程 b:等待数据后处理
    private static void threadB() {
        try {
            // 阻塞等待数据就绪
            latch.await();
            System.out.println("线程 B 收到数据: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 线程 c:等待数据后处理
    private static void threadC() {
        try {
            // 阻塞等待数据就绪
            latch.await();
            System.out.println("线程 C 收到数据: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:
在这里插入图片描述

2、使用kotlin协程的方式

思考:

协程 a 的异步执行:

1)使用 async 启动协程 a,返回一个 Deferred 对象(dataDeferred)。

2)在协程 a 中,通过 delay(1000) 模拟耗时操作,最终返回数据。

协程 b 和 c 的并发等待:

1)使用 launch 启动协程 b 和 c,它们会立即开始执行。

2)协程 b 和 c 调用 dataDeferred.await() 挂起自身,直到协程 a 的数据准备完毕。

数据共享与可见性:

1)Deferred 是 Kotlin 协程的轻量级并发原语,确保数据在协程间的安全传递。

2)await() 方法是非阻塞的,协程会在数据就绪后自动恢复执行。

import kotlinx.coroutines.*

fun main() = runBlocking {
    // 协程 a 异步生成数据,返回 Deferred 对象
    val dataDeferred = async {
        delay(1000) // 模拟耗时操作(如计算、IO)
        "Data from Coroutine A"
    }

    // 启动协程 b 和 c,它们会并发执行并等待数据
    val jobB = launch {
        val data = dataDeferred.await() // 挂起直到数据就绪
        println("Coroutine B 处理数据: $data")
    }

    val jobC = launch {
        val data = dataDeferred.await() // 挂起直到数据就绪
        println("Coroutine C 处理数据: $data")
    }

    // 等待所有子协程完成
    joinAll(jobB, jobC)
}

网站公告

今日签到

点亮在社区的每一天
去签到