Непонятное поведение потоков

348
01 июня 2017, 07:43

Пытаюсь сделать такую вещь: В консоль выводится вопрос. Если в течении некоторого времени пользователь не вводит ответ, то задаётся следующий вопрос. Если вводит ответ, то следующий вопрос задаётся сразу. Мой код:

public class Test {
private boolean stopQuestion;
Thread          scannerThread = new Thread();
public static void main(final String[] args) {
    final Test test = new Test();
    test.scannerThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                String string;
                do {
                    string = test.requestInput(new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(3000);
                            } catch (final InterruptedException e) {
                            }
                            test.scannerThread.interrupt();
                        }
                    }));
                } while (!test.stopQuestion);
                System.out.println("Input: " + string);
            } catch (final IOException e) {
                throw new RuntimeException(e);
            }
        }
    });
    test.scannerThread.start();
}
public String requestInput(final Thread timer) throws IOException {
    final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    timer.start();
    System.out.println("Any question");
    System.out.println("Please type your answer: ");
    try {
        while (!br.ready()) {
            Thread.sleep(100);
        }
    } catch (final InterruptedException e) {
        System.out.println("Time is over. Next question: ");
        return null;
    }
    System.out.println("Thank You for providing input!");
    return br.readLine();
}
}

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

Пробовал вынести реализацию которая передаётся в requestInput в отдельный экземпляр класса и передавать ссылку на этот экземпляр, но тогда выскакивает IllegalThreadStateException.

Answer 1

У Вас есть основной тред и треды, которые генерятся каждые 3 сек (назовем их треды-прерыватели).
Если Вы вводите текст, то основной тред раньше выходит из метода requestInput. Но тред-прерыватель все еще жив и готовится прервать основной тред. Основной тред создает новый тред-прерыватель и запускает его. У нас получаются два одновременно работающих треда-прерывателя. Тред-прерыватель, созданный первым, прерывает основной поток - причем конечно раньше, чем за 3 сек. И тем самым заставляет основной поток создать еще один тред-прерыватель. Т.е. получается, что одновременно будут существовать 2 треда-прерывателя. Если Вы будете продолжать вводить текст, то можно наплодить еще тредов-прерывателей.

Answer 2

Может вам сделать всего два потока: производитель (ждет пользовательское сообщение и передает его куда надо) и потребитель (обработка сообщения). Эти потоки создаются сразу и синхронизируются, например, через BlockingQueue.

READ ALSO
Не получает ключ с Firebase

Не получает ключ с Firebase

Проблема в том, что для удаления данных с Firebase мне необходимо знать ключ для удаленияЯ получаю snapshop, в режиме дебага вижу, что ключ приходит,...

496
Как проверить, имеется ли подстрока в строке

Как проверить, имеется ли подстрока в строке

Я не смог четко сформулировать вопросНо тем не менее вот:

368
Какой View передаётся параметром в onClick?

Какой View передаётся параметром в onClick?

Есть у нас кнопкаМы задаём ей onClick (назовём его так же — onClick)

291