Java创建两个线程但仅一个运行问题求助
排查多线程仅单线程执行的锁阻塞问题
嘿,我看到你遇到了启动两个Mechanics线程后只有一个干活的问题,而且已经怀疑是锁阻塞导致的——这个方向真的很靠谱!咱们结合你给出的代码片段(Shop、CarGenerator、Mechanics类),一步步拆解可能的问题点:
1. 先检查Shop类的锁机制是否存在独占问题
这是最可能导致锁阻塞的核心点:
- 如果
Shop里的核心方法(比如修车、取车)用了synchronized修饰,或者用了ReentrantLock,要确认锁的持有时间是否过长。比如某个Mechanics线程进入锁后,一直在执行循环逻辑(比如没有正确的终止条件,或者没在资源为空时释放锁等待),那另一个线程会一直被挡在锁外面,根本没机会执行。 - 举个反例:如果
Shop的修车方法是这样写的,第一个线程会一直占着锁不放:
public synchronized void repair() { // 错误:没有判断任务是否为空,空转占锁 while (true) { if (!cars.isEmpty()) { // 修车逻辑 } // 没有wait()释放锁,其他线程永远进不来 } }
正确的做法应该是在任务为空时调用wait()释放锁,让其他线程有机会获取:
public synchronized void repair() throws InterruptedException { while (cars.isEmpty()) { wait(); // 释放锁,进入等待状态 } // 修车逻辑 notifyAll(); // 通知其他等待的线程 }
2. 确认两个Mechanics线程是否都被正确启动
别笑,这是很容易忽略的小问题!检查你的Main方法里,是不是只调用了mechanics1.start(),漏掉了mechanics2.start()?如果只启动一个线程,那自然只有它在干活。
3. 检查共享资源的任务分配逻辑
如果CarGenerator生成的车辆任务太少,或者第一个线程把所有任务瞬间抢完了,第二个线程会因为没有任务可处理而处于等待状态,看起来就像没执行。你可以在Mechanics的run方法里加日志,比如每次获取到任务时打印"[Mechanics X] 开始修车",这样就能判断是真的没执行,还是没任务可做。
4. 检查锁的释放是否规范
如果用了ReentrantLock而不是synchronized,一定要确保在finally块里调用unlock()释放锁。如果线程在执行过程中抛出异常,没释放锁的话,另一个线程会永远拿不到锁:
// 错误示例:没在finally里释放锁 Lock lock = new ReentrantLock(); public void repair() { lock.lock(); if (someCondition) { throw new RuntimeException(); // 抛出异常后锁没释放 } lock.unlock(); } // 正确示例 public void repair() { lock.lock(); try { // 修车逻辑 } finally { lock.unlock(); // 无论是否异常,都会释放锁 } }
5. 排查线程是否因异常静默终止
有时候线程抛出了未捕获的异常,会直接终止,但你没看到日志,误以为它没执行。可以在Mechanics的run()方法外层加一个全局的异常捕获:
@Override public void run() { try { // 你的业务逻辑 } catch (Throwable e) { System.err.println("[" + name + "] 线程异常终止:" + e.getMessage()); e.printStackTrace(); } }
先从这几个方向排查,应该能找到问题所在!
内容的提问来源于stack exchange,提问作者liejoes1
相关产品推荐
相关产品推荐

