2017-07-11 17 views
1

我正在開發基於控制檯的Java應用程序。我必須向用戶顯示選擇數據庫的建議。我正在使用Scanner來讀取輸入,並使用單獨的線程來檢查輸入是否包含TAB以打印建議。基於控制檯的應用程序不顯示建議

UPDATE

按照下文答案,我添加同步塊代碼和異常消失。但是,我在控制檯上看不到任何建議。以下是我目前的代碼:

import java.util.ArrayList; 
import java.util.List; 
import java.util.Scanner; 

class Test { 

    private static List<String> suggestions = new ArrayList<>(); 

    private static final Object lock = new Object(); 

    public static void main(String[] arguments) { 

     suggestions.add("H2"); 
     suggestions.add("Mongo"); 
     suggestions.add("MySQL"); 
     suggestions.add("Oracle"); 
     suggestions.add("PostgreSQL"); 
     suggestions.add("SQLite"); 

     Scanner scanner = new Scanner(System.in); 
     System.out.println("Enter a database name, press TAB for suggestions"); 

     new Thread(new Runnable() { 
      public void run() { 
       while (true) { 
        synchronized (lock) { 
         if (scanner.hasNext()) { 
          String input = scanner.next(); 
          if (input.contains("\\t")) { 
           System.out.println(getSuggestions(input)); 
          } 
         } 
        } 
       } 
      } 
     }).start(); 

     synchronized (lock) { 
      String selectedDatabase = scanner.nextLine(); 
      System.out.println(selectedDatabase); 
     } 

    } 

    private static List<String> getSuggestions(String input) { 
     List<String> possibleSuggestions = new ArrayList<>(); 
     for (String suggestion : suggestions) { 
      if (suggestion.startsWith(input)) { 
       possibleSuggestions.add(suggestion); 
      } 
     } 
     return possibleSuggestions; 
    } 

} 

請問有人請幫忙嗎?

回答

3

簡而言之,Scanner不是一個線程安全的類,你在兩個不同的線程中使用它。

你在主線程中實例化掃描器,並在另一箇中使用它。在後臺,Scanner的構造函數可能已經初始化了不一定同步到另一個線程的字段。

而另一個線程運行時,您在主線程中執行scanner.nextLine(),該線程可能與另一個執行scanner.hasNext()的線程完全同時執行,導致併發訪問。

您需要一種方法來同步訪問掃描器(到處),例如,藉助於

synchronized (lock) { 
    if (scanner.hasNext()) { 
     String input = scanner.next(); 
     if (input.contains("\\t")) { 
      System.out.println("ok"); 
     } 
    } 
} 

在鎖定您的同步靜態字段:

private static final Object lock = new Object(); 
+0

所以是不是可以使用掃描儀用於此目的? – Beginner

+0

我試過你的答案,但仍然得到相同的例外。 – Beginner

+0

@Beginner您需要同步掃描器的所有訪問權限。不要忘記主線程中的scanner.nextLine()。 –

相關問題