如何向Java Thread传递对象参数?线程攻击玩家状态不生效求助
解决怪物自动攻击无法修改玩家状态的问题
核心问题分析
你的代码里run方法调用attack(player)时,大概率是怪物类的player成员变量未正确绑定玩家实例,或者存在线程可见性问题导致主线程无法读取到被修改的玩家HP。
分步解决方法
1. 确保怪物类持有正确的Player实例
在怪物类中添加成员变量并通过构造方法注入玩家实例,避免使用未初始化的player变量:
public class Monster extends Thread { private volatile boolean stop; private int att; // 怪物攻击力 private Player player; // 持有玩家实例 // 通过构造方法传入玩家 public Monster(Player player, int att) { this.player = player; this.att = att; this.stop = false; } @Override public void run() { while (!stop) { try { attack(player); Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 正确处理中断 return; } } } public void attack(Player player) { int damage = att - player.getDefence(); // 修正伤害计算逻辑,避免负数伤害 damage = Math.max(damage, 0); player.takeDamage(damage); } // 提供停止攻击的方法 public void stopAttack() { this.stop = true; } }
2. 修复Player类的线程安全问题
因为玩家HP是多线程共享变量,需要保证修改和读取的线程安全,避免主线程看不到更新:
public class Player { private volatile int hp; private int defence; public Player(int initialHp, int defence) { this.hp = initialHp; this.defence = defence; } // 用同步方法处理伤害,保证原子性 public synchronized void takeDamage(int damage) { if (damage > 0) { hp -= damage; // 防止HP变为负数 hp = Math.max(hp, 0); } } // 同步读取HP,保证可见性 public synchronized int getHp() { return hp; } public int getDefence() { return defence; } }
3. 正确启动怪物线程
在游戏主逻辑中创建玩家和怪物实例,启动线程:
public class GameMain { public static void main(String[] args) { Player player = new Player(100, 20); Monster monster = new Monster(player, 25); monster.start(); // 启动自动攻击线程 // 示例:主线程每隔1秒打印玩家HP try { for (int i = 0; i < 10; i++) { System.out.println("当前玩家HP: " + player.getHp()); Thread.sleep(1000); } monster.stopAttack(); // 停止怪物攻击 } catch (InterruptedException e) { e.printStackTrace(); } } }
关键注意点
stop变量必须声明为volatile,否则怪物线程可能无法及时感知到stop的变化,导致无法停止。- 共享变量(如Player的HP)的修改和读取需要保证线程安全,要么用
volatile保证可见性,要么用synchronized保证原子性和可见性。 - 避免直接修改Player的成员变量,通过封装的方法(如
takeDamage)操作,更易维护和保证安全。
内容的提问来源于stack exchange,提问作者Chanyoung
相关产品推荐
相关产品推荐

