java循环卡住,java程序卡在while循环中

博主在尝试将基于文本的冒险游戏从命令行迁移到JFrame GUI时遇到问题。游戏暂停功能依赖于一个布尔变量`buttonPressed`,在用户点击按钮后改变其状态以继续游戏。然而,程序的执行只在while循环中有`system.out.println`时才会继续。问题可能涉及线程同步和事件处理。建议使用信号量或`volatile`关键字确保变量更新的可见性,或者考虑使用对话框来正确地暂停程序流程。博客讨论了Java并发、GUI编程和事件处理的挑战。

我正在写一个基于文本的冒险游戏,我遇到了一个问题。 我正在将它从终端移植到JFrame GUI,我需要它在继续之前等待用户输入。 我建立了一个系统,其中有一个名为buttonPressed的布尔变量,它以false开头。 按下提交文本按钮后,将其更改为true。 有一个while循环在允许程序继续之前等待按钮变为true,基本上暂停程序直到用户提交输入。 问题是这只有当我在while循环中写入一个system.out.println行时才有效。否则它在我点击按钮后不会继续。 有什么问题?

public class event implements ActionListener{

public void actionPerformed(ActionEvent e){

moves += 1;

movesLabel.setText("Moves:" + moves);

buttonPressed = true;

try{

input = (String)(textfield.getText());

textfield.setText("");

}catch(Exception ex){

textfield.setText("Error");

}

}

}

public static void main (String args[]) {

Main gui = new Main();

gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

gui.setVisible(true);

gui.setSize(650, 350);

gui.setTitle("Sprinkles Text Adventure");

setInventory();

textArea.setText(textDisplay("Welcome Adventurer!"));

textArea.setText(textDisplay("What is thy name:"));

while(!buttonPressed){

// this only works when I have system.out.println("something") written in

}

buttonPressed = false;

textArea.setText(textDisplay(input));

if ("alice".equals(input)||"Alice".equals(input)){

textArea.setText(textDisplay("Stop toking the magical pipe,"));

textArea.setText(textDisplay("you aren't alice and this isn't wonderland"));

textArea.setText(textDisplay("Now down the rabbit hole you go!"));

}

else if ("l3ikezI".equals(input)||"l3ikezi".equals(input)){

System.out.println("Magic and Technology flows through your veins");

System.out.println("Welcome back, Master");

for(int j = 0; j<14; j++){

Chest[j]=1;

}

}

else{

System.out.println("Enter" + input +" and good luck!

");

}

你定义了buttonPressed吗?

是的,在顶部我用private static boolean buttonPressed = false初始化它; 这很奇怪,因为当我有一行代码时,它可以工作

然后我猜想JVM会跳过空的无限循环。 也许你可以使用Thread.sleep(15)?

缺少buttonPressed定义......看起来你有两个? 用不完整的代码很难说。

你能提供更多代码吗? 如何将ActionListener附加到按钮?

我首先看看Java中的Concurrency。 我还要看看如何制作能够解决基本问题的对话框

我没有java专家,但......

看起来你没有给你的gui线程时间做任何事情,因为你正忙着等待你的布尔值改变。

要解决这个问题,你应该使用信号量。或者,更容易(脏)的解决方案,在while循环中调用sleep()。

对于java特定的东西,请看这个问题。

第二个想法,我发现java有一个volatile关键字。我不知道buttonPressed是否被声明为volatile,但如果不是,编译器可能会决定,因为while循环是空的,它的值永远不会改变,并用while(true)替换它作为优化。

这个...

while(!buttonPressed){

// this only works when I have system.out.println("something") written in

}

只是要求麻烦,除了你不能保证实际调用了什么线程main,这可能导致你阻塞事件调度线程,这只是错误的方法。

您不想使用JFrame,而是使用某种模式JDialog,这将阻止代码在对话框可见时执行,直到它被处理/关闭,并以安全的方式执行,因此您可以在EDT的背景下使用它。

有关更多详细信息,请查看初始线程,Swing中的并发以及如何创建对话框。

作为一般建议,避免直接从顶级容器(如JFrame和JDialog)扩展,而是选择使用JPanel之类的东西,它可以让您解放并增加组件的可重用性

<think>好的,我现在需要帮用户解决Java多线程程序卡住停止的问题,尤其是死锁和饥饿的原因。首先,我得回忆一下Java多线程的基础知识,以及常见的并发问题。用户提到了死锁和饥饿,这两个确实是多线程中常见的问题。先从死锁开始。死锁发生的四个必要条件我记得是互斥、持有并等待、不可抢占、循环等待。需要解释清楚每个条件,然后说明在Java中如何产生,比如多个线程互相持有对方需要的锁,导致互相等待。可能还需要例子,比如用户提供的生产者-消费者模型中用到了ReentrantLock,如果两个线程分别持有不同的锁,并且试图获取对方持有的锁,就会死锁。然后是饥饿,饥饿指的是线程长时间无法获取所需资源,无法执行。可能的原因包括高优先级线程抢占资源,或者某些线程长时间占用锁而不释放。比如在生产者-消费者模型中,如果生产者一直快速生产,消费者可能因为无法获得锁而饥饿。不过用户提供的示例用了Condition,可能避免了这种情况,但如果线程调度不公平,还是可能发生饥饿。接下来,用户可能还遇到了其他问题,比如活锁或者资源耗尽。活锁是线程在不断尝试解决冲突,但始终无法进展,比如两个线程互相让步。资源耗尽比如线程池配置不当,或者内存泄漏导致系统资源不足,线程无法继续执行。还需要考虑代码中的同步问题,比如是否正确使用了锁,是否在正确的地方释放了锁。比如在生产者-消费者示例中,lock.unlock()放在finally块中,确保锁会被释放,避免死锁。但如果代码中有嵌套锁或者多个锁的顺序不当,仍然可能死锁。 另外,线程卡住还可能是因为等待条件未满足,比如在Condition.await()时,没有其他线程调用signal(),导致永久等待。这时候需要检查是否有遗漏的信号通知,或者条件判断是否正确使用了while循环而不是if,避免虚假唤醒的问题。 用户给的示例代码中,生产者和消费者都使用了while循环来检查条件,这是正确的做法,可以防止虚假唤醒。但如果在其他地方错误地使用了if,可能会导致问题。可能还需要提到如何诊断这些问题,比如使用jstack生成线程转储,查看线程的状态和锁持有情况,找出死锁的位置。或者用VisualVM等工具监控线程状态。 最后,生成相关问题的时候,要考虑用户可能的后续疑问,比如如何避免死锁、检测死锁的方法、饥饿的其他原因,或者活锁的情况,以及如何设计公平锁来避免饥饿。要确保回答结构清晰,分点解释原因,并给出示例和解决方案。同时,引用用户提供的生产者-消费者模型代码作为例子,说明正确使用锁和条件变量的方法,避免死锁和饥饿。可能还需要提到其他原因,比如线程池配置错误导致的任务堆积,或者单个任务执行时间过长,导致线程卡住。但用户主要关注的是死锁和饥饿,所以重点放在这两个方面。总结下来,回答的结构应该是先概述问题,然后分点详细解释死锁和饥饿的原因,给出示例,再扩展到其他可能原因,最后给出诊断方法和解决方案,并生成相关问题。</think>### Java多线程程序卡住停止的原因分析 #### 1. 死锁(Deadlock) **原因**:当多个线程**互相持有对方需要的锁**且无法释放时,会陷入永久等待。需满足四个必要条件: - **互斥**:资源只能被一个线程占用 - **持有并等待**:线程持有资源同时请求其他资源 - **不可抢占**:资源只能由持有线程主动释放 - **循环等待**:多个线程形成环形等待链 **示例**: ```java // 线程1 synchronized (A) { synchronized (B) { ... } } // 线程2 synchronized (B) { synchronized (A) { ... } } ``` 此时两个线程可能永久阻塞[^1]。 #### 2. 饥饿(Starvation) **原因**:某些线程**长期无法获得必要资源**,常见于: - 线程优先级设置不合理 - 资源分配策略不公平 - 存在"贪婪线程"长期占用资源 **示例**:在生产者-消费者模型中,若生产者持续快速生成数据,消费者可能因无法获取CPU时间片而无法消费数据[^2]。 #### 3. 其他潜在原因 - **活锁(Livelock)**:线程不断改变状态却无法推进(如反复重试失败操作) - **资源耗尽**:线程池过小、内存泄漏导致系统资源枯竭 - **无限等待**:未正确触发`Condition.signal()`,导致线程在`await()`中永久阻塞 #### 诊断工具 1. 使用`jstack`生成线程转储,查看线程状态和锁持有情况 2. JConsole/VisualVM可视化监控线程状态 3. 静态代码分析工具检查同步逻辑 #### 解决方案 | 问题类型 | 解决方法 | |---------|----------| | 死锁 | 使用`tryLock()`定时获取锁<br>统一锁获取顺序<br>减少同步代码块范围 | | 饥饿 | 使用公平锁(`new ReentrantLock(true)`)<br>合理设置线程优先级 | | 活锁 | 引入随机退避机制<br>重构资源竞争逻辑 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值