2015-09-01 6 views
0

Хорошо, мне немного сложно найти эту ошибку, прежде чем я проведу другой день, я просто спрошу вас, ребята.Хотя цикл продолжает работать, хотя условие ложно

//Core Class 
static String serverAnswer = ""; 

public static void sendMessage(String msg){ 
    serverAnswer = ""; 
    Connection.send(msg); 
    while(serverAnswer.equals(""));  <infinity loop 
} 

//Connection Thread 
public void run() { 
    while(running){ 
     try { 
      msg = (String)in.readObject(); 
      Core.serverAnswer = msg; 
     } catch (StreamCorruptedException e){ 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

На самом деле поток не должен ждать, пока ответа сервера, а затем установить ответ

поэтому цикл должен остановиться, но я доза не остановить ...

Я проверил следующее:

  • thread is running: yes
  • проблема определенно бесконечная петля
  • Core.serverAnswer Определенно получить строку с сервера.

Так что-нибудь о while() Я не знаю или не знаю, где может быть проблема?

+7

* «Проведя еще один день, я попрошу вас, ребята». * Отладчик - ваш друг ... – HyperZ

+3

Можете ли вы показать полный код? –

+0

Где вы указываете что-либо для 'serverAnswer'? – krillgar

ответ

8

Если вы не используете volatile, JVM может свободно вводить значение. В частности, он может свободно оптимизировать чтение и никогда не проверять его снова.

Вам необходимо сделать свое поле volatile.

Один из способов нарушить эту оптимизацию для обеспечения безопасной работы потока.

while(serverAnswer.equals("")) 
    Thread.yield(); 

Однако лучшим решением будет читать объекты в BlockingQueue

public class TextSocket implements Closeable { 
    final Socket socket; 
    private final BufferedReader reader; 
    private final PrintWriter writer; 

    public TextSocket(String hostname, int port) throws IOException { 
     this(new Socket(hostname, port)); 
    } 

    public TextSocket(Socket socket) throws IOException { 
     this.socket = socket; 
     reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); 
     writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8)); 
    } 

    public String sendAndRead(String msg) throws IOException { 
     writer.println(msg); 
     if (writer.checkError()) 
      throw new IOException("Unable to write"); 
     writer.flush(); 
     return reader.readLine(); 
    } 

    @Override 
    public void close() throws IOException { 
     socket.close(); 
    } 
} 

Я также предлагаю вам избегать использования статических полей, как это. Вы можете реализовать свое Connection, используя поля экземпляра, которые позволят вам иметь более одного, если хотите.

+0

Спасибо, что @Peter 'volatile' исправил его на данный момент. Но я хотел бы знать цель BlockingQueue, если вы не возражаете объяснить это и свое предложение, так как я действительно знаю, что статические поля быстрее, и у меня есть статический доступ к ним, и пока у меня есть необходимость в что один вар не лучше использовать его как статичный? Потому что в противном случае я вынужден передать экземпляр «Core» ко всему, что работает с 'serverAnswer', не так ли? – erinas

+0

@erinas Вы можете добавить объект в BlockingQueue в поток чтения и использовать 'queue.take()' в потребляющем потоке. Это будет заблокировано, пока не будет прочитан объект. Это также поточно-безопасный. –

Смежные вопросы