2017-05-30 85 views
0

我正在嘗試這樣做:問題顯示在控制檯中。如果在一段時間內用戶沒有寫出答案,那麼就會問下一個問題。如果用戶輸入答案,則立即詢問下一個問題。我的代碼:奇怪的線程行爲

public class Test { 
private boolean stopQuestion; 
Thread   scannerThread = new Thread(); 

public static void main(final String[] args) { 
    final Test test = new Test(); 

    test.scannerThread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       String string; 
       do { 
        string = test.requestInput(new Thread(new Runnable() { 

         @Override 
         public void run() { 
          try { 
           Thread.sleep(3000); 
          } catch (final InterruptedException e) { 
          } 
          test.scannerThread.interrupt(); 

         } 
        })); 
       } while (!test.stopQuestion); 

       System.out.println("Input: " + string); 
      } catch (final IOException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    }); 
    test.scannerThread.start(); 

} 

public String requestInput(final Thread timer) throws IOException { 
    final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

    timer.start(); 

    System.out.println("Any question"); 
    System.out.println("Please type your answer: "); 
    try { 
     while (!br.ready()) { 
      Thread.sleep(100); 
     } 
    } catch (final InterruptedException e) { 
     System.out.println("Time is over. Next question: "); 
     return null; 
    } 
    System.out.println("Thank You for providing input!"); 
    return br.readLine(); 
} 

}

如果你不寫東西到控制檯,一切似乎都按預期運行。時間結束,下一個問題被問到。但是,如果有東西寫入控制檯,定時器開始出現故障,下一個問題不會等待指定的時間,有時它根本不會等待。我不明白是怎麼回事。

我在方法外部創建了線程實例,並將實例作爲引用傳遞給該方法,但隨後引發IllegalThreadStateException。

+2

這裏似乎有幾件事情是錯誤的,但突出的兩件事是'stopQuestion'的可見性和從多個線程訪問'System.in'的整個想法。哦,'sleep()'也不能用於準確的時間安排,絕對沒有與之相關的保證。 – biziclop

+1

此外,如果用戶輸入了答案的一半,然後再打印另一個問題,輸入緩衝區中的輸入文本仍然存在,所以這會非常容易混淆。你的前提是有缺陷的,即你所要做的是不會與控制檯程序一起工作。 – Andreas

+0

我剛纔注意到,你使用'interrupt()'來推測重複信號,這聽起來不是一個好主意。 – biziclop

回答

0

我看到了兩個主要問題與您的代碼:

  1. 您是汽車無創造,都應該讀線程輸入:

      do { 
           string = test.requestInput(new Thread(new Runnable() { 
    
            @Override 
            public void run() { 
             try { 
              Thread.sleep(3000); 
             } catch (final InterruptedException e) { 
              e.printStackTrace(); 
             } 
             test.scannerThread.interrupt(); 
    
            } 
           })); 
          } while (!test.stopQuestion); // <-- this is always true 
    
  2. 您在System.in開放盡可能多的BufferedReader S作爲許多定時器線程正在啓​​動:

    final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    

此外,您沒有關閉這些BufferedReader實例中的任何一個。

+0

如果關閉'BufferedReader',則關閉'System.in',並防止將來所有輸入讀取。不要關閉包裝在System.in中的讀取器/掃描器/輸入流。 – Andreas

+0

應該只有一個'BufferedReader'的實例,它應該最終關閉。 – syntagma

+1

它永遠不應該關閉。 'System.in'由Java運行時管理,不應該被應用程序關閉。 – Andreas