java无限while循环的奇怪行为



我有这个简单的网络代码(我试图实现一个简单的聊天服务器作为练习),但我被卡住了,我不知道发生了什么。我为我的客户端创建了GUI,它有一个另一个类的实例,它执行所有必要的操作,以连接和发送/接收消息到我的服务器。

package com.luca.chat;
import java.awt.*
import java.awt.event.*
import javax.swing.*
class Window extends JFrame {
  private final static int WIDTH=500;
  private final static int HEIGHT=300;
  private String status="disconnected";
  private JPanel panel;
  private JTextArea area;
  private JTextField field,address;
  private JButton button;
  private JLabel label;
  private IOClass io=new IOClass(this);
  Window() {
    super("Chit-Chat");
    setSize(new Dimension(WIDTH,HEIGHT));
    ImageIcon icon=new ImageIcon("..\images\lucas.png");
    setIconImage(icon.getImage());
    JPanel contentPane=(JPanel)getContentPane();
    // add the text area to display incoming and outgoing messages
    area=new JTextArea();
    area.setEditable(false);
    contentPane.add(area,BorderLayout.CENTER);
    // add text field to send messages
    field=new JTextField(20);
    field.addActionListener(new ActionListener(){ 
      public void actionPerformed(ActionEvent e) {
        String message=field.getText();
        io.send(message);
        field.setText("");
      }
    });
    panel=new JPanel();
    panel.add(field);
    panel.setBorder(BorderFactory.createEtchedBorder());
    contentPane.add(panel,BorderLayout.SOUTH);
    // add status bar on top 
    label=new JLabel("status: "+status);  
    address=new JTextField(15);
    button=new JButton("connect");
    panel=new JPanel();  
    panel.add(label);
    panel.add(address);
    panel.add(button);  
    button.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        io.connect(address.getText());
      }
    }); 
    panel.setBorder(BorderFactory.createEtchedBorder());
    contentPane.add(panel,BorderLayout.NORTH);
    Toolkit kit=getToolkit();
    Dimension dim=kit.getScreenSize();
    setLocation((dim.width-WIDTH)/2,(dim.height-HEIGHT)/2);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
    loop();
  }
  void loop() { 
    while (true) 
      if (io.connected) 
        io.receive(); 
      else            // if I comment this line out it never calls receive() ?????    
        System.out.println("????"); 
  }
  void setStatus(String status) {
    label.setText(status);
  }
  void setText(String received) {
    area.append(received);
  }
  public static void main(String[] args) {
    new Window();
  }

}

IOClass拥有连接/发送/接收的所有方法(我认为它的行为就像一个控制器?我不知道,我刚刚开始学习这个模式)一个标志,它控制连接是否建立。如果有连接,它会调用receive方法,这是一个用于侦听传入消息的无限循环。

但是,如果我只留下if语句(在loop()内部)而不留下else。。。它不执行!我的意思是。。while循环永远不会开始(我尝试了一些打印……它永远不会到达那里),但如果我添加其他打印,它就会到达那里!

例如,这会阻塞if语句:

 void loop() { 
   while (true) 
     if (io.connected) 
       io.receive(); 
 }

这是有效的(while永远循环):

 void loop() { 
   while (true) 
     if (io.connected) 
       io.receive();   
     else
        ....do something else...
 }

或者甚至这样做:

 void loop() {
   while (true) { 
     System.out.println("whatever"); 
     if (io.connected) 
       io.receive();
   }  // end of while
 }

我不能理解,这在我看来是一种非常奇怪的行为

EDIT:使用Eclipse的调试功能,我看到当它工作时,while循环会按预期永远循环,当它不工作时,它只会在if条件下阻塞

void loop() { 
    while (true) 
      if (io.connected) 
        io.receive(); 
      else  // if I comment this line out it never calls receive() ?????    
        System.out.println("????"); 
}

在您的答案示例中,您指出此代码是罪魁祸首。由于while没有括号{},因此只有下一行将被视为while循环的主体。没有括号的if也是如此:只有true条件中的第一行才会执行。它后面可以跟else-子句,也可以不跟。

在您的情况下,由于while之后的下一行是if-else,并且这两个条件都只有一行要执行,所以while循环按预期工作。

如果你想说的是:

void loop() { 
    while (true) 
      if (io.connected) 
        io.receive(); 
      //else   
        System.out.println("????"); 
}

那么这就不会编译,因为您告诉System.out.println("????");执行AFTERwhile循环已经完成,while循环的条件明确为true;永远无法访问代码。如果您使用一个变量作为标志,它将进行编译,并且当循环完成时,您将体验到System.out.println("????");将执行一次。

在Eclipse调试器的帮助下,我一步一步地找到了捕获。由于当我实例化一个JFrame时,JVM会自动旋转一个新线程(事件队列),并且由于是用连接按钮注册的ActionListener调用connect()方法将布尔标志设置为true,因此该标志在这个线程中为true,但在主线程中仍然为false,因此if条件永远不会计算为true,我挂起等待receive()方法被调用,屏幕上没有输出。使用volatile修饰符解决了这个问题,因此更新后的变量对所有线程都是自动可见的。由于我是线程的新手,所以这并不那么明显。。但一句话让我走上了正确的方向。

相关内容

  • 没有找到相关文章

最新更新