Java 基于控制台的应用程序不';不要提出建议

Java 基于控制台的应用程序不';不要提出建议,java,console-application,java.util.scanner,Java,Console Application,Java.util.scanner,我正在开发一个基于控制台的Java应用程序。我必须向用户显示选择数据库的建议。我正在使用扫描仪读取输入,并使用一个单独的线程检查输入是否包含选项卡,以便打印建议 更新 根据下面的回答,我在代码中添加了synchronized块,异常消失了。但是,我没有看到控制台上打印任何建议。以下是我目前的代码: import java.util.ArrayList; import java.util.List; import java.util.Scanner; class Test { priv

我正在开发一个基于控制台的Java应用程序。我必须向用户显示选择数据库的建议。我正在使用
扫描仪
读取输入,并使用一个单独的线程检查输入是否包含
选项卡
,以便打印建议

更新

根据下面的回答,我在代码中添加了synchronized块,异常消失了。但是,我没有看到控制台上打印任何建议。以下是我目前的代码:

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;
    }

}
import java.util.ArrayList;
导入java.util.List;
导入java.util.Scanner;
课堂测试{
私有静态列表建议=新建ArrayList();
私有静态最终对象锁=新对象();
公共静态void main(字符串[]参数){
建议。添加(“H2”);
建议。添加(“Mongo”);
建议。添加(“MySQL”);
建议。添加(“Oracle”);
建议。添加(“PostgreSQL”);
建议。添加(“SQLite”);
扫描仪=新的扫描仪(System.in);
System.out.println(“输入数据库名称,按TAB键获取建议”);
新线程(newrunnable()){
公开募捐{
while(true){
已同步(锁定){
if(scanner.hasNext()){
字符串输入=scanner.next();
如果(输入.包含(\\t“)){
System.out.println(getSuggestions(input));
}
}
}
}
}
}).start();
已同步(锁定){
字符串selectedDatabase=scanner.nextLine();
System.out.println(selectedDatabase);
}
}
私有静态列表getSuggestions(字符串输入){
列出可能的建议=新建ArrayList();
对于(字符串建议:建议){
if(建议启动(输入)){
可能的建议。添加(建议);
}
}
返回可能的建议;
}
}

有人能帮忙吗?

简单地说,
Scanner
不是线程安全类,您在两个不同的线程中使用它

您在主线程中实例化扫描器并在另一个线程中使用它。在后台,Scanner的构造函数可能初始化了不一定与另一个线程同步的字段

当另一个线程运行时,您在主线程中执行一个
scanner.nextLine()
,该线程可能与另一个执行
scanner.hasNext()
的线程同时执行,从而导致并发访问

您需要一种方法来同步对扫描仪的访问(在任何地方),例如通过锁定

其中,锁是您同步的静态字段:

private static final Object lock = new Object();

所以不能使用扫描器进行此操作吗?我尝试了您的答案,但仍然得到相同的异常。@初学者您需要同步对扫描器的所有访问。不要忘记主线程中的
scanner.nextLine()
。好的,异常现在消失了。但是,我没有看到关于按
TAB
键的建议。有什么问题吗?
private static final Object lock = new Object();