您现在的位置是:java学习笔记 >
java学习笔记
[共享变量] java主线程获取子线程数据
本 文 目 录
Java主线程获取子线程数据
在多线程编程中,主线程和子线程间的通信是常见且重要的场景。主线程可能需要获取子线程执行后的计算结果或者其他中间状态信息。本文将详细介绍如何在Java中实现主线程获取子线程的数据,主要运用的方法是通过共享变量、Future接口以及CountDownLatch等同步工具。
步骤一:利用共享变量
- 定义共享变量
创建一个共享对象或变量,该变量对主线程和子线程都可见。例如,可以声明一个volatile修饰的变量,确保多线程环境下的可见性和有序性。
public class SharedData {
public volatile String result;
}
- 子线程修改共享变量
在子线程的任务代码中,完成计算后更新共享变量。
Thread childThread = new Thread(() -> {
// 执行耗时操作
String computedResult = someComputation();
sharedData.result = computedResult;
});
childThread.start();
- 主线程读取共享变量
主线程可以通过轮询或者wait-notify机制检测共享变量是否已更新,从而获取到子线程的计算结果。
while (sharedData.result == null) {
// 等待子线程计算完成并更新结果
Thread.sleep(100);
}
System.out.println("主线程获取到的结果:" + sharedData.result);
步骤二:使用Future与Callable
- 创建Callable任务
使用Callable接口替代Runnable接口创建子线程任务,因为Callable能够返回一个值。
Callable<String> callableTask = () -> {
// 执行耗时操作
return someComputation();
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(callableTask);
- 主线程获取Future结果
主线程可以通过调用Future对象的get()方法来阻塞等待子线程执行完成,并获取其结果。
try {
String resultFromChild = future.get();
System.out.println("主线程获取到的结果:" + resultFromChild);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 不再接受新任务,关闭线程池
executor.shutdown();
步骤三:利用CountDownLatch
- 初始化CountDownLatch
创建一个CountDownLatch实例,计数值设为1,表示我们需要等待一个事件发生。
CountDownLatch latch = new CountDownLatch(1);
- 子线程完成任务后countDown
子线程在完成计算后调用countDown()方法。
Thread childThread = new Thread(() -> {
// 执行耗时操作
String computedResult = someComputation();
sharedData.result = computedResult;
latch.countDown(); // 计数器减一
});
childThread.start();
- 主线程await获取结果
主线程调用await()方法阻塞等待子线程完成,并获取结果。
latch.await(); // 阻塞直到计数器为0
System.out.println("主线程获取到的结果:" + sharedData.result);
总结与注意事项:
- 共享变量方式简单直观,但需注意并发控制,如使用volatile保证可见性。
- Future与Callable结合的方式提供了更优雅的线程间数据传递方案,但需管理好线程池资源。
- CountDownLatch适用于多个线程等待某个事件(如所有子线程完成)的情况,它能更好地协调线程间的同步。
完整代码示例 - 使用Future与Callable:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MainThreadGetSubThreadDataExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> callableTask = () -> {
// 模拟耗时操作
Thread.sleep(1000);
return "子线程计算结果";
};
Future<String> future = executor.submit(callableTask);
String resultFromChild = future.get();
System.out.println("主线程获取到的结果:" + resultFromChild);
// 关闭线程池
executor.shutdown();
}
}