我正在开发一个基于控制台的 Java 应用程序。我必须向用户展示选择数据库的建议。我正在使用 Scanner
读取输入,并使用一个单独的线程检查输入是否包含 TAB
以便打印建议。
更新
按照下面的回答,我在代码中添加了同步块(synchronized block),异常消失了。但是,我没有在控制台上看到任何建议。以下是我当前的代码:
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;
}
}
有人可以帮忙吗?
最佳答案
简单地说,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();
关于java - 基于控制台的应用程序不显示建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45036600/