2017-07-11 63 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()。 –

相关问题