线程使用中的值传递问题:多线程类实例间如何传递数据?
嘿,这个问题我熟!当你有两个由第三方类启动的独立线程,要让它们之间传递值,核心是用线程安全的通信机制——毕竟多线程环境下直接共享数据很容易触发竞态条件(比如读的时候数据还没写完)。下面给你几个实用的Java方案(默认是Java场景,其他语言思路类似),附代码示例,你可以根据需求选:
方案1:线程安全的共享对象(带同步锁)
这是最基础的方式:创建一个专门的共享数据容器,给它的读写方法加上同步锁,让两个线程持有同一个容器实例,通过容器来传递数据。还可以用wait()/notify()实现线程间的同步等待,避免忙轮询。
// 线程安全的共享数据容器 public class SharedData { private String value; private boolean isReady = false; // 写方法:加同步锁保证原子性,数据未被读取时等待 public synchronized void setValue(String value) { while (isReady) { try { wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } this.value = value; isReady = true; notify(); // 通知读线程数据已准备 } // 读方法:同样同步,数据未准备时等待 public synchronized String getValue() { while (!isReady) { try { wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } isReady = false; notify(); // 通知写线程可以写入新数据 return value; } }
然后是两个工作线程类:
// 写数据的线程类 public class WriterTask implements Runnable { private final SharedData sharedData; public WriterTask(SharedData sharedData) { this.sharedData = sharedData; } @Override public void run() { for (int i = 0; i < 5; i++) { String data = "消息" + i; System.out.println("写线程发送:" + data); sharedData.setValue(data); try { Thread.sleep(1000); // 模拟业务耗时 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } // 读数据的线程类 public class ReaderTask implements Runnable { private final SharedData sharedData; public ReaderTask(SharedData sharedData) { this.sharedData = sharedData; } @Override public void run() { for (int i = 0; i < 5; i++) { String data = sharedData.getValue(); System.out.println("读线程接收:" + data); try { Thread.sleep(1500); // 模拟业务耗时 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
最后是启动两个线程的主类:
public class ThreadStarter { public static void main(String[] args) { SharedData sharedData = new SharedData(); Thread writerThread = new Thread(new WriterTask(sharedData)); Thread readerThread = new Thread(new ReaderTask(sharedData)); writerThread.start(); readerThread.start(); } }
适用场景:一对一的同步通信,逻辑清晰,适合入门理解线程通信原理。
方案2:使用
BlockingQueue(推荐) Java并发包提供的BlockingQueue天生就是为线程间通信设计的,它自带线程安全和阻塞特性——队列空时读线程自动阻塞,队列满时写线程自动阻塞,不用手动加锁和处理等待逻辑,代码更简洁可靠。
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; // 写线程类 public class WriterTask implements Runnable { private final BlockingQueue<String> queue; public WriterTask(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 0; i < 5; i++) { String data = "消息" + i; System.out.println("写线程发送:" + data); queue.put(data); // 队列满时自动阻塞 Thread.sleep(1000); } queue.put("结束"); // 发送任务结束信号 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } // 读线程类 public class ReaderTask implements Runnable { private final BlockingQueue<String> queue; public ReaderTask(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { try { String data; while (!(data = queue.take()).equals("结束")) { // 队列空时自动阻塞 System.out.println("读线程接收:" + data); Thread.sleep(1500); } System.out.println("读线程收到结束信号,退出"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } // 启动类 public class ThreadStarter { public static void main(String[] args) { // 容量为1的队列,模拟一对一同步通信;如果是多生产者/消费者可以调大容量 BlockingQueue<String> queue = new ArrayBlockingQueue<>(1); Thread writerThread = new Thread(new WriterTask(queue)); Thread readerThread = new Thread(new ReaderTask(queue)); writerThread.start(); readerThread.start(); } }
适用场景:所有生产者-消费者场景,不管是一对一还是多对多,代码维护成本低,是工业界常用的方案。
方案3:使用
CompletableFuture(异步结果传递) 如果其中一个线程是计算出结果后再传递给另一个线程,CompletableFuture是更好的选择——它支持异步回调,不用手动管理线程等待,还能优雅处理异常。
import java.util.concurrent.CompletableFuture; // 生成结果的线程类 public class ProducerTask implements Runnable { private final CompletableFuture<String> future; public ProducerTask(CompletableFuture<String> future) { this.future = future; } @Override public void run() { try { Thread.sleep(2000); // 模拟耗时计算 String result = "计算结果:100"; future.complete(result); // 完成任务并设置结果 } catch (InterruptedException e) { future.completeExceptionally(e); // 异常时标记任务失败 Thread.currentThread().interrupt(); } } } // 接收结果的线程类 public class ConsumerTask implements Runnable { private final CompletableFuture<String> future; public ConsumerTask(CompletableFuture<String> future) { this.future = future; } @Override public void run() { try { String result = future.get(); // 阻塞等待结果(也可以用thenAccept异步处理) System.out.println("接收线程获取到结果:" + result); // 后续业务逻辑 } catch (Exception e) { System.err.println("获取结果失败:" + e.getMessage()); } } } // 启动类 public class ThreadStarter { public static void main(String[] args) { CompletableFuture<String> future = new CompletableFuture<>(); Thread producerThread = new Thread(new ProducerTask(future)); Thread consumerThread = new Thread(new ConsumerTask(future)); producerThread.start(); consumerThread.start(); } }
适用场景:异步结果传递,比如一个线程做计算/IO,另一个线程等待结果处理;还可以用thenAccept()、thenApply()等方法实现链式异步操作,不用单独开消费线程。
内容的提问来源于stack exchange,提问作者L.Dassanayake
相关产品推荐
相关产品推荐

