【问题标题】:Console Based Application Doesn't Show Suggestions基于控制台的应用程序不显示建议
【发布时间】:2017-07-11 13:55:47
【问题描述】:

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

更新

根据以下答案,我在代码中添加了同步块,异常消失了。但是,我没有在控制台上看到任何建议。以下是我当前的代码:

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

}

有人可以帮忙吗?

【问题讨论】:

    标签: java console-application java.util.scanner


    【解决方案1】:

    简单地说,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();
    

    【讨论】:

    • 那么是不是不能使用 Scanner 来达到这个目的?
    • 我试过你的答案,但仍然得到同样的异常。
    • @Beginner 您需要同步对扫描仪的所有访问。不要忘记主线程中的scanner.nextLine()
    • 好的,异常现在消失了。但是,我没有看到有关按 TAB 键的建议。可能是什么问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 2011-04-04
    相关资源
    最近更新 更多