如何获取类结束时变量的最终值及跨类访问该值?
解决方案:30秒后获取并访问Game类的变量最终值
针对你的两个问题,我结合现有代码给出调整方案,解决死循环、定时停止、变量获取和跨类访问的问题:
1. 让Game类在30秒后结束并获取变量最终值
你的现有代码里Game构造函数是死循环while(true),定时器无法终止它,所以首先要添加一个线程安全的停止标志,让定时器能通知Game停止循环,之后就能在循环结束后打印变量。
修改后的Game类:
import java.io.IOException; public class Game { // volatile保证多线程下可见性,定时器线程修改后主线程能立刻看到 private volatile boolean isRunning = true; private int true_num = 0, false_num = 0; // 建议封装,用getter访问 public Game() throws InterruptedException, IOException { // 把Game实例传给TimerDemo,让定时器能通知停止 new TimerDemo(30, this); while (isRunning) { play(); Thread.sleep(100); // 加个小休眠,避免CPU空转 } // 循环结束后,打印最终值 printFinalValues(); } private void play() { // 模拟变量变化逻辑,你可以替换成自己的代码 if (Math.random() > 0.5) true_num++; else false_num++; } // 供定时器调用,停止循环 public void stopGame() { isRunning = false; } private void printFinalValues() { System.out.println("=== 程序运行结束 ==="); System.out.println("true_num最终值: " + true_num); System.out.println("false_num最终值: " + false_num); } // 提供getter方法,供其他类访问变量 public int getTrueNum() { return true_num; } public int getFalseNum() { return false_num; } }
对应的TimerDemo类修改,让它能触发Game停止:
import java.awt.Toolkit; import java.util.Timer; import java.util.TimerTask; public class TimerDemo { Toolkit toolkit; Timer timer; private Game gameInstance; public TimerDemo(int seconds, Game game) { this.gameInstance = game; toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); // 延迟指定秒数后执行停止任务 timer.schedule(new TimerTask() { @Override public void run() { gameInstance.stopGame(); timer.cancel(); // 取消定时器,释放资源 } }, seconds * 1000); } }
2. 从另一个类访问Game的变量最终值
有两种常用方式,根据你的场景选择:
方式一:直接通过Game实例的getter访问
如果你的调用类可以等待Game运行结束,直接在Game构造完成后调用getter方法即可:
public class GameViewer { public static void main(String[] args) { try { Game game = new Game(); // Game构造函数会阻塞到30秒结束,之后可以直接获取值 System.out.println("\n--- 从GameViewer访问的最终值 ---"); System.out.println("true_num: " + game.getTrueNum()); System.out.println("false_num: " + game.getFalseNum()); } catch (InterruptedException | IOException e) { e.printStackTrace(); } } }
方式二:观察者模式(异步监听)
如果其他类不想阻塞等待,而是希望Game结束时主动通知,可以用观察者模式:
首先定义一个监听接口:
public interface GameEndListener { void onGameFinished(int trueNum, int falseNum); }
修改Game类,添加监听列表和通知逻辑:
import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Game { private volatile boolean isRunning = true; private int true_num = 0, false_num = 0; private List<GameEndListener> endListeners = new ArrayList<>(); public Game() throws InterruptedException, IOException { new TimerDemo(30, this); while (isRunning) { play(); Thread.sleep(100); } // 通知所有注册的监听器 notifyGameEnd(); printFinalValues(); } // 添加注册监听器的方法 public void addGameEndListener(GameEndListener listener) { endListeners.add(listener); } private void notifyGameEnd() { for (GameEndListener listener : endListeners) { listener.onGameFinished(true_num, false_num); } } // 其他方法不变... }
然后实现监听器的类:
public class AsyncGameMonitor implements GameEndListener { public static void main(String[] args) { try { Game game = new Game(); // 注册监听器 game.addGameEndListener(new AsyncGameMonitor()); // 这里可以执行其他任务,不用等待30秒 System.out.println("正在后台监控Game运行..."); } catch (InterruptedException | IOException e) { e.printStackTrace(); } } @Override public void onGameFinished(int trueNum, int falseNum) { System.out.println("\n--- AsyncGameMonitor收到结束通知 ---"); System.out.println("true_num最终值: " + trueNum); System.out.println("false_num最终值: " + falseNum); } }
关键注意点
- volatile关键字:必须用它修饰停止标志
isRunning,因为定时器的任务是在独立线程执行的,volatile能保证主线程及时看到标志的变化,避免死循环。 - 封装变量:把
true_num和false_num改成private,用getter方法访问,符合面向对象的封装原则,也能方便后续添加线程安全控制。 - 避免CPU空转:在循环里加
Thread.sleep(100),防止程序占用过高CPU资源。
内容的提问来源于stack exchange,提问作者ParisaN
相关产品推荐
相关产品推荐

