Как обрабатывать разные сканеры в разных темах - PullRequest
0 голосов
/ 12 января 2019

Чтобы избежать проблемы XY, я собираюсь объяснить контекст: Я делаю приложение чата в режиме консоли. Пользователь может отправить текст или файл. Если пользователь получает файл, на консоли выводится «Новый файл получен! Где вы хотите его сохранить?:».

Теперь проблема: У меня есть while(true) цикл в моем Main.java, где я спрашиваю пользователя, что он хочет сделать, например, «отправить», чтобы отправить сообщение, или «сеансы», чтобы напечатать беседы с пользователями. Таким образом, в этом цикле есть scanner.nextLine().

У меня есть поток listener.java, где я слушаю о TCP-соединении, и когда я получаю файл в TCP, я хочу выполнить scanner.nextLine(), чтобы спросить пользователя «Где вы хотите сохранить его?». Но я не могу этого сделать, потому что мои listener.java и мой Main.java мешают двум сканерам одновременно прослушивать один и тот же поток ( System.in ).

Я попробовал решение, указанное здесь Несколько сканеров в нескольких потоках , но оно не работает. Я попытался синхронизировать сканер, но мне кажется, что мой поток не смог заблокировать сканер. Тот же результат с реентрантным замком ...

Я написал фрагмент кода, чтобы вы поняли, о чем я говорю, это не мой настоящий код, но он воспроизводит мою проблему, поток, который выполняет sc.nextLine () одновременно с Main.

public static void main(String [] args) throws IOException, InterruptedException {
    Scanner sc = new Scanner(System.in);

    Thread tt = new Thread(new Runnable() {
        @Override
        public void run() {

            try {
                //The thread wait...
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
            }

            String test= "";
            //Here i receive a file so i ask the user where he wants to save it...
            synchronized (sc) {
                System.out.print("New file received ! where do you want to save it ? ");
                test = sc.nextLine();
            }
            System.out.println("File written : " + test);
        }
    });
    tt.start();

    System.out.print("Main blabla ? ");
    String bb = "";
    while(true) {
        synchronized (sc) {
            bb = sc.nextLine();

        }
        System.out.print("blabla : " + bb);
        //Do actions.....
    }
}

1 Ответ

0 голосов
/ 12 января 2019

Использование нескольких Scanner s для чтения из одного потока кажется хрупким. Приложение получило бы выгоду от инкапсуляции функциональности взаимодействия с пользователем таким образом, чтобы поток и сканер не могли быть доступны другим частям кодовой базы напрямую. Абстракция должна реализовывать командный цикл и обрабатывать события, поступающие извне, например, получение файла.

Получение событий должно быть соответствующим образом синхронизировано и идеально помещено в очередь, чтобы новые события могли быть получены, пока пользователь отвечает на предыдущее событие. В общем, абстракция взаимодействия с пользователем всегда будет делать только одно - чтение ответа пользователя на следующее событие или следующую команду, если событий нет. Это было, будет один поток и Scanner, предназначенный для чтения входного потока.

...