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

调用wait()方法后JFrame显示空白、应用程序冻结问题求助

问题根源

  • 第一,你阻塞了Swing的事件调度线程(EDT):Swing采用单线程渲染模型,所有UI重绘、用户输入事件回调(包括你写的dispatchKeyEvent)都必须在EDT上执行。如果你是在EDT中调用了sharedObject.wait(),会直接挂起EDT,既无法触发JFrame重绘导致界面变白,也无法执行键盘输入的回调逻辑,notify永远不会被触发,程序直接死锁。
  • 第二,锁对象不匹配:你等待的对象是sharedObject,但键盘逻辑中调用notify的是lockObject,两个是完全独立的对象,就算EDT没有被阻塞,notify也无法唤醒等待中的线程。

修复方案

步骤1:拆分游戏逻辑线程和UI线程

把游戏主逻辑、等待输入的逻辑放到单独的子线程中运行,绝对不要在EDT中执行任何阻塞操作。所有需要修改UI的操作,再通过SwingUtilities.invokeLater()抛回EDT执行,示例代码如下:

// 游戏初始化时启动独立的逻辑线程
new Thread(() -> {
    boolean gameRunning = true;
    while (gameRunning) {
        // 等待玩家输入
        try {
            synchronized (lockObject) {
                lockObject.wait();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            break;
        }
        // 处理玩家输入逻辑(角色移动、数值计算等非UI操作)
        processPlayerMove(playerInput);
        // 涉及UI更新的操作必须抛回EDT执行
        SwingUtilities.invokeLater(() -> {
            // 在这里执行更新角色位置、刷新界面、重绘地图等UI操作
            updateGameUI();
        });
    }
}).start();

步骤2:统一锁对象

保证等待逻辑和通知逻辑使用同一个锁对象,把你原有的等待代码里的sharedObject替换成和键盘逻辑一致的lockObject即可。

可选优化

你可以用CountDownLatch、CompletableFuture这类JUC工具代替原始的wait/notify,代码可读性更高,也更不容易出现锁匹配错误的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:15:08