如何让Java线程实现并发执行?
问题根源与解决方案
看起来你是把生产者和消费者的逻辑放在同一个线程里顺序执行了!不管你在Create方法里加多少sleep,只要是单线程顺序调用,就一定会等Create完全执行完,才会轮到Consume启动——这根本不是并发执行,自然做不到一边生产一边消费的效果。
要实现生产者-消费者模式,核心是把生产和消费逻辑放到独立的线程中运行,同时用线程安全的共享容器来传递对象,避免并发操作导致的数据问题。下面给你具体的实现思路和代码示例:
核心解决步骤
- 用线程安全的队列替代自定义堆:推荐
java.util.concurrent.LinkedBlockingQueue,它自带阻塞等待机制,不用自己写轮询或同步逻辑。 - 将生产、消费逻辑封装为
Runnable:让它们能在独立线程中运行。 - 启动独立线程分别执行生产和消费逻辑,实现并发运行。
完整示例代码
import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; // 假设这是你要生产/消费的对象类型 class MyTask { private int id; public MyTask(int id) { this.id = id; } public int getId() { return id; } } // 生产者逻辑:往队列中添加对象 class Producer implements Runnable { private final LinkedBlockingQueue<MyTask> sharedQueue; private final int totalTasks; public Producer(LinkedBlockingQueue<MyTask> queue, int totalTasks) { this.sharedQueue = queue; this.totalTasks = totalTasks; } @Override public void run() { Random random = new Random(); try { for (int i = 0; i < totalTasks; i++) { // 模拟生产耗时(比如创建对象的时间) Thread.sleep(random.nextInt(1000)); MyTask newTask = new MyTask(i); sharedQueue.put(newTask); // 队列满时自动阻塞等待 System.out.println("生产任务: ID=" + newTask.getId()); } } catch (InterruptedException e) { // 优雅处理线程中断 Thread.currentThread().interrupt(); System.out.println("生产者线程被中断"); } } } // 消费者逻辑:从队列中移除对象 class Consumer implements Runnable { private final LinkedBlockingQueue<MyTask> sharedQueue; public Consumer(LinkedBlockingQueue<MyTask> queue) { this.sharedQueue = queue; } @Override public void run() { Random random = new Random(); try { while (!Thread.currentThread().isInterrupted()) { MyTask task = sharedQueue.take(); // 队列空时自动阻塞等待 // 模拟消费耗时(比如处理对象的时间) Thread.sleep(random.nextInt(1000)); System.out.println("消费任务: ID=" + task.getId()); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("消费者线程被中断"); } } } public class JavaApplication2 { public static void main(String[] args) throws InterruptedException { // 初始化线程安全的共享队列 LinkedBlockingQueue<MyTask> taskQueue = new LinkedBlockingQueue<>(); // 设定生产者要生产的总任务数 int totalProduction = 5; // 创建并启动生产者线程 Thread producerThread = new Thread(new Producer(taskQueue, totalProduction)); // 创建并启动消费者线程 Thread consumerThread = new Thread(new Consumer(taskQueue)); producerThread.start(); consumerThread.start(); // 等待生产者完成所有生产任务 producerThread.join(); // 给消费者留时间处理剩余任务,然后优雅中断它 Thread.sleep(1500); consumerThread.interrupt(); consumerThread.join(); System.out.println("所有生产消费任务完成"); } }
关键细节说明
- 线程安全的队列:
LinkedBlockingQueue的put()和take()方法是线程安全的,并且自带阻塞机制——当队列满时,生产者会自动等待;当队列空时,消费者会自动等待,不用你手动写同步锁或轮询逻辑。 - 独立线程运行:生产者和消费者在各自的线程中执行,所以它们的操作是并发的,你会看到控制台中生产和消费的日志交替输出,实现了你要的"一边添加一边移除"的效果。
- 优雅停止线程:用
interrupt()中断线程,而不是强制杀死,这样能保证线程有机会清理资源,避免内存泄漏。
额外注意点
- 如果你坚持要用自己实现的"堆",一定要给它加上线程安全的同步措施(比如用
synchronized块,或者用ReentrantLock),否则并发操作会出现数据丢失、重复消费等问题。但更推荐直接用JUC包下的线程安全集合,效率和可靠性都更高。 - 如果需要多个生产者或多个消费者,只需要多创建几个对应的线程并启动即可,队列会自动协调它们的操作。
内容的提问来源于stack exchange,提问作者Some_Dude
相关产品推荐
相关产品推荐

