Java中如何按FIFO顺序控制Cat对象线程依次执行meow方法?
实现Cat对象按固定顺序执行meow方法的简单方案
原代码中使用synchronized (Cat.class)作为类锁,只能保证同一时间只有一个线程执行meow,但JVM的线程调度无法保证执行顺序。以下是几种简单的实现方式,确保cat1→cat2→cat3的FIFO执行逻辑:
方式一:使用公平锁(ReentrantLock)
替换原有synchronized为公平锁,公平锁会严格按照线程请求锁的顺序分配锁,从而保证执行顺序。
import java.util.concurrent.locks.ReentrantLock; public class Cat { // 初始化公平锁,参数true表示公平模式 private static final ReentrantLock fairLock = new ReentrantLock(true); public void meow() { fairLock.lock(); try { System.out.println("meow"); } finally { // 必须在finally中释放锁,避免异常导致锁泄漏 fairLock.unlock(); } } }
使用时需确保线程的启动顺序为cat1对应的线程先启动,接着是cat2、cat3,这样请求锁的顺序才会符合预期。
方式二:用CountDownLatch手动控制执行顺序
无需修改Cat类的原有逻辑,通过CountDownLatch让每个线程等待前一个线程执行完成后再启动。
import java.util.concurrent.CountDownLatch; public class Main { public static void main(String[] args) throws InterruptedException { Cat cat1 = new Cat(); Cat cat2 = new Cat(); Cat cat3 = new Cat(); CountDownLatch latchForCat2 = new CountDownLatch(1); CountDownLatch latchForCat3 = new CountDownLatch(1); // 启动cat1的线程,执行完成后通知cat2 new Thread(() -> { cat1.meow(); latchForCat2.countDown(); }).start(); // cat2的线程等待cat1完成后执行,完成后通知cat3 new Thread(() -> { try { latchForCat2.await(); cat2.meow(); latchForCat3.countDown(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); // cat3的线程等待cat2完成后执行 new Thread(() -> { try { latchForCat3.await(); cat3.meow(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); } }
方式三:使用单线程线程池
将所有执行meow的任务提交到单线程线程池,线程池会按任务提交顺序依次执行,天然满足FIFO要求。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { Cat cat1 = new Cat(); Cat cat2 = new Cat(); Cat cat3 = new Cat(); // 创建单线程线程池 ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); // 按顺序提交任务 singleThreadPool.submit(cat1::meow); singleThreadPool.submit(cat2::meow); singleThreadPool.submit(cat3::meow); // 关闭线程池 singleThreadPool.shutdown(); } }
方案选择
- 如果允许修改
Cat类内部逻辑,公平锁是最直接的方案; - 如果需要保留原有
Cat类的实现,CountDownLatch或单线程线程池更合适,其中单线程池的代码实现最为简洁。
内容的提问来源于stack exchange,提问作者user122025
相关产品推荐
相关产品推荐

