正常运行时代码不工作,但在调试(eclipse)中工作

我对此感到困惑:当我在eclipse中正常运行我的程序时,我的一些代码无法正常工作,但是当我使用调试模式单独运行每个步骤时,它确实发生了故障。

码:

public void showConnectDialog() { ConnectDialog connectDialog = new ConnectDialog(); connectDialog.setVisible(true); //Until here, code runs while(! connectDialog.getConnected()) {}; //The next line does only run in debug JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE); } 

连接器(一旦用户在对话框中点击“连接”)就启动(作为线程):

 private class ServerConnector implements ActionListener, Runnable { @Override public void actionPerformed(ActionEvent e) { if (! IP_field.getText().equals("")) { if (! isConnecting) { new Thread(new ServerConnector(), "ServerConnector").start(); } } else { JOptionPane.showMessageDialog(dialog, "Enter an IP address", "Enter IP", JOptionPane.WARNING_MESSAGE); } } @Override public void run() { try { setConnecting(true); Socket socket = connect(); if (socket != null) { ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream()); if (login(oOut, oIn)) { isConnected = true; setConnecting(false); } else { socket.close(); } setConnecting(false); } } catch (RSPException e) { e.printStackTrace(); System.exit(1); } catch (Exception e) { //If an exception occurs, setConnecting() will be true. This //not good, so it has to be set to false e.printStackTrace(); setConnecting(false); } } private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn) throws ClassNotFoundException, IOException, RSPException { //Send login request action: oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(), getPassword())); Object obj = oIn.readObject(); if (obj instanceof LoginActionResult) { LoginActionResult result = (LoginActionResult) obj; if (result.getResult() == LoginResults.SUCCES) { return true; } else if (result.getResult() == LoginResults.FAIL_ON_ID) { JOptionPane.showMessageDialog(dialog, "Invalid password or ID", "Can't login", JOptionPane.ERROR_MESSAGE); return false; } else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) { JOptionPane.showMessageDialog(dialog, "Invalid password or ID", "Can't login", JOptionPane.ERROR_MESSAGE); return false; } else if (result.getResult() == LoginResults.SERVER_FULL) { JOptionPane.showMessageDialog(dialog, "Couldn't connect: \n" + "Server is full", "Failed to connect", JOptionPane.WARNING_MESSAGE); return false; } else { return false; } } else { System.out.println(obj); throw new RSPException("Server is not following the protocol."); } } private void setConnecting(boolean connecting) { if (connecting) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setEnabled(false); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setText("Connecting..."); } }); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setText("Connect"); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setEnabled(true); } }); } isConnecting = connecting; } private String getAddressFromTextField() { return IP_field.getText(); } private InetAddress getInetAddress(String fullAddress) { try { if (fullAddress.contains(":")) { String[] splitAddress = fullAddress.split(":"); return InetAddress.getByName(splitAddress[0]); } else { return InetAddress.getByName(fullAddress); } } catch (UnknownHostException e) { return null; } } private int getPort(String fullAddress) { try { String[] splittedAddress = fullAddress.split(":"); return Integer.valueOf(splittedAddress[1]); } catch (NumberFormatException ex) { return -1; } catch (NullPointerException | ArrayIndexOutOfBoundsException | PatternSyntaxException ex) { //Returning default port value: 25566, because no port was given return 25566; } } @SuppressWarnings("resource") private Socket connect() { Socket socket = null; InetAddress address = null; if ((address = getInetAddress(getAddressFromTextField())) == null) { return null; } int port = getPort(getAddressFromTextField()); try { socket = new Socket(address, port); } catch (ConnectException e ) { Socket retrySocket = null; if ((retrySocket = retryConnect(address, port)) == null) { JOptionPane.showMessageDialog(dialog, "Connection timed out", "Failed to connect", JOptionPane.ERROR_MESSAGE); setConnecting(false); } else { socket = retrySocket; } } catch(IOException e) { e.printStackTrace(); } return socket; } private Socket retryConnect(InetAddress address, int port) { Thread waitThread = new Thread(new Runnable() { @Override public void run() { try { //Will wait 15(000) (milli)seconds before stopping with //trying to connect. //One second (1000 millis) is for debugging and testing Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); waitThread.start(); while (waitThread.isAlive()) { try { return new Socket(address, port); } catch (ConnectException e) { //Do nothing, will re-attempt to connect. } catch (IOException e) { e.printStackTrace(); } } return null; } private String getID() { return ID_field.getText(); } private String getPassword() { if (getID().equals("master")) { return "masterPassword"; } else { return new String(passwordField.getPassword()); } } } 

getConnected()在连接到服务器后立即返回true 。 连接器在单独的线程上运行。

编辑 :我试图将代码放在getConnected() while块中,然后它工作。 为什么它会起作用而不是其他?

我有同样的问题,但有一些更多的规范。 代码在32位工作正常,但我在64位有这个问题(我使用本机库,所以我需要维护两者)。

我找到的解决方案是在while循环中添加Thread.sleep()。 我不知道它为什么会起作用,所以你的猜测和我的一样好。

更好的解决方案可能是实现观察者模式而不是无限循环。 但这需要一些重新分解。

我有一个非常类似的问题,一个“while”循环不会运行,并且该循环是我的主要例程。 如何让循环运行是在循环中完成的第一件事是睡眠:

  try {Thread.sleep(0);} catch (Exception e) {e.printStackTrace();} 

这足以让一切顺利。

正如其他答案所建议的那样,使用Thread.sleep()应该可以解决问题,但这不是一个很好的方法。 相反,我们应该使用Thread.yield()

为什么yield而不sleep

请参阅: Thread.Sleep(0)和Thread.Yield()之间的区别以及Thread.sleep(0)和Thread.yield()语句是否相同?

为什么会这样?

当我们只运行线程时,操作系统将它们置于“空闲”状态,当它被“唤醒”时,它就不会。 另一方面,在调试模式下,我们有一个受控环境。 操作系统几乎无法控制它,因为一切都在逐步,缓慢地进行。 如果我们运行调试几次没有任何断点,在几次成功运行后,我们应该看到相同的效果。

我在UIAutomator中遇到了与UiObject2等待的问题(Until.findObject(),20)。

Thread.yield() – 适合我