Java多线程同步:同父类乐器实例互斥实现方案咨询
嘿,我来帮你解决这个同一父类下乐器实例互斥演奏的问题!
核心思路很明确:给每个抽象父类(String、Wind、Arc)分配一个类级别的独占锁,这样同一父类的所有乐器实例在执行演奏逻辑时,必须先抢到这个锁才能运行,自然就保证了同一时间只有一个实例演奏。
因为你的子类都没重写run()方法,所以我们只需要在三个抽象父类的run()里加锁逻辑就行,具体步骤和代码示例如下:
1. 改造抽象父类的run()方法
每个抽象父类的run()方法中,使用自身的Class对象作为类级锁,把核心的演奏逻辑包裹在synchronized块里。这样同一父类的所有实例都会竞争这同一个锁,实现互斥执行。
以Wind类为例:
public abstract class Wind extends Thread { @Override public void run() { // 使用Wind类对象作为类级锁,同一父类的所有实例共享这个锁 synchronized (Wind.class) { // 调用子类实现的演奏逻辑 play(); } } // 抽象演奏方法,由子类具体实现 public abstract void play(); }
同理,String和Arc类做完全相同的改造,只需要把锁对象换成String.class和Arc.class即可。
2. 乐器子类示例
比如一个属于Wind子类的长笛:
public class Flute extends Wind { @Override public void play() { System.out.println(Thread.currentThread().getName() + " 正在吹奏长笛..."); try { // 模拟演奏时长 Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(Thread.currentThread().getName() + " 长笛演奏结束"); } }
再比如属于String子类的小提琴:
public class Violin extends String { @Override public void play() { System.out.println(Thread.currentThread().getName() + " 正在拉小提琴..."); try { Thread.sleep(1500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(Thread.currentThread().getName() + " 小提琴演奏结束"); } }
3. 测试Main类验证效果
我们可以创建多个同一父类的实例,启动线程看看互斥效果:
public class Main { public static void main(String[] args) { // Wind类的两个实例:长笛和萨克斯 Thread flute = new Flute(); flute.setName("长笛线程"); Thread saxophone = new Saxophone(); saxophone.setName("萨克斯线程"); // String类的两个实例:小提琴和吉他 Thread violin = new Violin(); violin.setName("小提琴线程"); Thread guitar = new Guitar(); guitar.setName("吉他线程"); // 启动所有线程 flute.start(); saxophone.start(); violin.start(); guitar.start(); } }
运行后你会看到:
- 长笛和萨克斯不会同时演奏,必须等其中一个结束后另一个才开始
- 小提琴和吉他不会同时演奏,但它们可以和长笛/萨克斯同时进行(因为用的是不同的类锁)
方案可行性说明
- 类锁(
Xxx.class)属于类本身,所有该类的实例共享这一个锁,所以同一父类的实例会互斥执行synchronized块里的代码 - 不同父类的锁是各自独立的,所以不同类型的乐器可以同时演奏,不会互相影响
- 因为子类没有重写
run(),所以父类的锁逻辑会被所有子类继承,不需要修改子类代码,完全符合你的需求
内容的提问来源于stack exchange,提问作者Nicola Bernardi
相关产品推荐
相关产品推荐

