Java 基于控制台的应用程序不';不要提出建议
我正在开发一个基于控制台的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
扫描仪
读取输入,并使用一个单独的线程检查输入是否包含选项卡
,以便打印建议
更新
根据下面的回答,我在代码中添加了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();