Java主线程无需阻塞等待子线程先执行任务、接收子线程结果后再处理的实现方法
实现方案
核心逻辑:子线程启动后与主线程并行运行互不阻塞,主线程优先执行完0-4打印逻辑后,再阻塞等待子线程返回结果,执行后续任务。
方案1:基于Thread.join() + volatile修饰状态变量
该方案改动最小,仅需对你的原有代码做少量调整:
- 给
RunnableExample的isAvailable加volatile修饰,保证主线程能感知到子线程对该变量的修改,同时对外暴露状态和线程实例的获取方法。
修改后的RunnableExample代码:
public class RunnableExample implements Runnable { // 加volatile保证多线程间的变量可见性 volatile boolean isAvailable = false; Thread thread; public RunnableExample() { thread = new Thread(this); thread.start(); } public void run() { isAvailable = checkForAvailability(); } private boolean checkForAvailability() { // 模拟耗时任务 try { Thread.sleep(1000); } catch (Exception e) { Thread.currentThread().interrupt(); } return true; } // 对外暴露获取执行结果的方法 public boolean isAvailable() { return isAvailable; } // 对外暴露线程实例供join调用 public Thread getThread() { return thread; } }
- 主线程打印完成后调用
join()等待子线程执行结束,再拿结果执行后续逻辑。
修改后的RunnableTest代码:
public class RunnableTest { public static void main(String[] args) throws InterruptedException { // 启动子线程,此时子线程和主线程并行运行 RunnableExample runnableExample = new RunnableExample(); // 主线程优先执行打印0-4的逻辑,不受子线程影响 for (int i = 0; i < 5; i++) { System.out.println(i); } // 打印完成后,等待子线程执行完成 runnableExample.getThread().join(); // 拿到结果执行后续任务 boolean result = runnableExample.isAvailable(); System.out.println("拿到子线程结果:" + result + ",开始执行后续任务"); // 此处写后续业务逻辑 } }
方案2:基于Callable+FutureTask(生产级推荐实现)
如果不需要兼容老代码,更推荐用JDK自带的并发工具类实现,无需自行维护状态变量,也不用手动处理多线程可见性问题。
- 自定义Callable实现类执行耗时任务返回结果:
import java.util.concurrent.Callable; public class AvailabilityTask implements Callable<Boolean> { @Override public Boolean call() throws Exception { // 模拟耗时任务 Thread.sleep(1000); return true; } }
- 主线程代码:
import java.util.concurrent.FutureTask; public class RunnableTest { public static void main(String[] args) throws Exception { // 包装自定义任务 FutureTask<Boolean> futureTask = new FutureTask<>(new AvailabilityTask()); // 启动子线程执行任务 new Thread(futureTask).start(); // 主线程先执行打印0-4的逻辑 for (int i = 0; i < 5; i++) { System.out.println(i); } // 打印完成后阻塞等待子线程返回结果 Boolean result = futureTask.get(); System.out.println("拿到子线程结果:" + result + ",开始执行后续任务"); // 此处写后续业务逻辑 } }
内容的提问来源于stack exchange,提问作者Srikant
相关产品推荐
相关产品推荐

