You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何在不同类实例启动的线程间共享锁同步执行?

问题描述

我尝试在Application类中创建一个共享锁,并将其传递给创建线程的方法参数,希望让一个类实例启动的线程与另一个类实例启动的线程实现同步。

抽象类Alpha的start(Object sharedLock)方法用于创建新线程,原代码如下:

public abstract class Alpha {
   public abstract void test();

   public void start(Object sharedLock) {
      Thread t = new Thread(() -> {
         while(true) {
            synchronized(sharedLock) {
               test();
            }
            try {
               TimeUnit.SECONDS.sleep(db.timeInterval);
            } catch(InterruptedException e) {
                 Thread.currentThread().interrupt();
            }
        }
      });
      t.start(); // 原代码遗漏线程启动逻辑
   }
}

Alpha有两个子类Beta和Gama,Application类的run方法调用它们的start()方法:

@Override
public void run(String... args) {
    Object sharedLock = new Object(); // 补充共享锁实例创建
    Beta beta = new Beta();
    Gama gama = new Gama();
    beta.start(sharedLock);
    gama.start(sharedLock);
}

Beta和Gama重写了test()方法:

public class Beta extends Alpha {
   @Override
   public void test() {
      ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
      final int[] count = {1};
   
      Runnable task = new Runnable() {
         @Override
         public void run() {
            System.out.println(count[0]);
            count[0]++;

            if (count[0] > 20) {
               executor.shutdown();
            }
         }
      };
      executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
   }
}

public class Gama extends Alpha {
   @Override
   public void test() {
      System.out.println("Gama thread");
   }
}

需求:同一时间仅能有一个线程执行test()相关逻辑,例如Beta先获取锁的话,要完整打印1到20后,Gama才能执行;同时当持有锁的线程休眠时,其他线程可获取锁执行。

问题分析

原代码核心问题:

  • Beta的test()仅完成定时任务的提交,synchronized块只保护了任务提交过程,没有覆盖定时任务的整个执行周期。synchronized块执行完test()后就释放锁,此时Gama的线程会立刻进入同步块执行自己的逻辑,导致Beta的定时任务和Gama的输出同时进行。
  • Alpha中的while(true)会不断重复进入同步块调用test(),即使Beta的定时任务还未完成,会重复创建线程池和提交任务,造成逻辑混乱。
解决方案

要实现需求,需确保Beta的整个定时任务周期都被共享锁保护,同时调整Alpha的循环逻辑避免重复执行。具体修改如下:

1. 调整Alpha类

修改逻辑,让每个线程按需执行同步逻辑,同时预留循环执行的扩展空间:

public abstract class Alpha {
   public abstract void executeWithLock(Object sharedLock);

   public void start(Object sharedLock) {
      Thread t = new Thread(() -> {
         while (!Thread.currentThread().isInterrupted()) {
            try {
               executeWithLock(sharedLock);
               // 执行完成后休眠,休眠期间锁被释放,其他线程可竞争
               TimeUnit.SECONDS.sleep(db.timeInterval);
            } catch(InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
         }
      });
      t.start();
   }
}

2. 修改Beta类

将同步范围覆盖到定时任务的整个执行周期,等待任务全部完成后再释放锁:

public class Beta extends Alpha {
   @Override
   public void executeWithLock(Object sharedLock) {
      synchronized(sharedLock) {
         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
         final int[] count = {1};
   
         Runnable task = new Runnable() {
            @Override
            public void run() {
               System.out.println(count[0]);
               count[0]++;

               if (count[0] > 20) {
                  executor.shutdown();
               }
            }
         };
         executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);

         // 等待线程池所有任务完成,确保整个打印过程都在锁保护下
         try {
            executor.awaitTermination(1, TimeUnit.HOURS); // 设置足够长的超时时间
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             executor.shutdownNow();
         }
      }
   }
}

3. 修改Gama类

在共享锁保护下执行自身逻辑:

public class Gama extends Alpha {
   @Override
   public void executeWithLock(Object sharedLock) {
      synchronized(sharedLock) {
         System.out.println("Gama thread");
      }
   }
}
关键说明
  • 必须将所有需要同步的逻辑都放在共享锁的保护范围内,对于Beta来说,就是从任务创建到全部完成的完整流程。
  • 使用executor.awaitTermination()等待定时任务结束,避免提前释放锁导致同步失效。
  • Alpha的循环逻辑确保线程执行完一次任务后休眠,休眠期间锁被释放,其他线程可以竞争获取锁执行,符合需求。

内容的提问来源于stack exchange,提问作者ot954

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:04:52