多线程实现咨询:Thread B不得超前Thread A的约束方案探讨
问题解答
你的sleep方案评估
- 这个方案没有从根本上保证约束条件:
Thread.sleep(10)是基于时间的“猜测性”同步,线程调度完全由操作系统控制,一旦A线程因系统负载过高、GC等原因出现延迟,B线程的sleep时间可能不足以等待A完成对应数字的打印,最终还是会出现B超前于A的情况。 - 多线程特性确实保留了:两个线程是同时运行的,只是B线程被强制延迟执行,但这种方式既不高效(无端浪费CPU等待时间),也不严谨,属于并发编程中的反模式。
更可靠的实现方式
方式1:共享计数器+锁同步
通过一个共享计数器变量,配合synchronized锁控制线程执行顺序,保证B只能打印A已经处理过的数字:
public class ThreadPrinter { private int count = 0; private final Object lock = new Object(); public void printA() { synchronized (lock) { while (count < 100) { System.out.println("Thread A: " + (++count)); lock.notify(); try { if (count < 100) lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } lock.notify(); } } public void printB() { synchronized (lock) { while (count < 100) { try { lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } if (count <= 100) { System.out.println("Thread B: " + count); lock.notify(); } } } } public static void main(String[] args) { ThreadPrinter printer = new ThreadPrinter(); new Thread(printer::printA).start(); new Thread(printer::printB).start(); } }
方式2:使用Semaphore(信号量)
用两个信号量控制线程的执行许可,A完成一个数字打印后释放许可给B,B打印完成后再释放许可给A,以此交替执行:
import java.util.concurrent.Semaphore; public class SemaphorePrinter { private final Semaphore aPermit = new Semaphore(1); private final Semaphore bPermit = new Semaphore(0); private int count = 0; public void printA() { try { while (count < 100) { aPermit.acquire(); System.out.println("Thread A: " + (++count)); bPermit.release(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public void printB() { try { while (count < 100) { bPermit.acquire(); System.out.println("Thread B: " + count); aPermit.release(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static void main(String[] args) { SemaphorePrinter printer = new SemaphorePrinter(); new Thread(printer::printA).start(); new Thread(printer::printB).start(); } }
单个Runnable对象的实现
完全可以通过单个Runnable对象实现,核心是利用共享状态+同步机制,让不同线程根据自身身份执行对应逻辑:
public class SharedRunnable implements Runnable { private int count = 0; private final Object lock = new Object(); @Override public void run() { String threadRole = Thread.currentThread().getName(); synchronized (lock) { while (count < 100) { if ("A".equals(threadRole)) { // A线程负责递增并打印数字 System.out.println("Thread A: " + (++count)); lock.notify(); } else { // B线程等待A完成递增后再打印 try { lock.wait(); } catch (InterruptedException e) { return; } if (count <= 100) { System.out.println("Thread B: " + count); lock.notify(); } } // 避免A线程连续抢占锁,给B线程执行机会 try { if (count < 100) lock.wait(); } catch (InterruptedException e) { return; } } } } public static void main(String[] args) { SharedRunnable sharedTask = new SharedRunnable(); new Thread(sharedTask, "A").start(); new Thread(sharedTask, "B").start(); } }
内容的提问来源于stack exchange,提问作者Tarun Soni
相关产品推荐
相关产品推荐

