Тест
Контейнер с потокобезопасной работой с парами ключ-значение:- ConcurentSkipListSet
- CopyOnWriteArrayList
- ConcurentHashMap
- ConcurentSkipListMap
Нужно ли при отправке ответного сообщения обращаться к AddressService?
- да
- нет, обратный адрес есть в самом сообщении в поле from
Нужно ли помечать thread-local объекты словом volatile?
- нет
- да
Нужно ли опередить private Map<Address, ConcurrentLinkedQueue<Msg>> messages через ConcurrentHashMap?
- нет, потому что мы не добавляем в процессе работы сервера новые абоненты в карту, а чтение безопасно из нескольких потоков
- да, потому что нам нужен доступ к этому объекту из нескольких потоков
В плюсы многопоточного решения для аутентификации пользователя НЕ входит:
- эффективное использование потоков библиотеки jetty
- масштабирование (возможность создать несколько AccountService)
- возможность независимой коллективной разработки
- синхронное взаимодействие Frontend и AccountService
- малое время ожидание ответа пользователем
Выполнение инструкций сообщения происходит:
- в потоке получателя
- в дополнительном потоке
- в потоке отправителя
Нужно ли использовать при объявлении private Map<Address, ConcurrentLinkedQueue<Msg>> messages в классе MessageSsytem ключевое слово volatile?
- нет, потому что заполнение карты происходит до старта потоков в методе main()
- да, потому что нам нужен доступ к этому объекту из нескольких потоков
Контейнер, который копирует объекты при вставке:
- ConcurentSkipListMap
- ConcurentHashMap
- CopyOnWriteArrayList
- ConcurentSkipListSet
ConcurrentLinkedQueue:
- контейнер, который копирует объекты при вставке
- потокобезопасный контейнер пар ключ-значение
- потокобезопасная очередь
Класс Address при реализации системы сообщения нужен:
- для того, чтобы создать карту, в которой ключ это адрес, а значение - очередь C сообщений для получателя с этим адресом
- для того, чтобы хранить адрес пользователя в AccountService
- для того, чтобы передавать адрес пользователя в браузер
- для того, чтобы идентифицировать получателя и отправителя сообщения
Объект UserSession при повторном логине пользователя из другого браузера:
- объекты будут разные, но userSessionId в них будет одинаковым
- тот же что и при первом логине
- новый
Что НЕ верно для Frontend?
- может произвести аутентификацию пользователя и найти его id по имени
- объект, в котором jetty вызывает handle(...) при открытии страниц сервера пользователем
- метод run() этого объекта запущен в отдельном потоке
- хранит данные пользовательских сессий
ConcurrentHashMap – это карта, в которой все методы synchronized?
- да
- нет
Класс Msg:
- абстрактный класс - предок всех сообщений
- интерфейс, который должны реализовывать все сообщения
- инстанцируемый класс, содержащий данные сообщения
Контейнер, построенный с использованием списка:
- ConcurentSkipListSet
- CopyOnWriteArrayList
- ConcurentHashMap
- ConcurentSkipListMap
Какие варианты решения проблемы взаимодействия потоком могут быть расширены на взаимодействие процессов (запущенных на разных компьютерах)?
- менять состояние общего для потоков объекта
- передавать сообщения через систему обмена сообщениями
- держать в каждом потоке ссылки на все остальные потоки
- передавать сообщения через общий ресурс
Проверка на abonent instanceof в наследниках класса Msg нужна:
- для проверки правильности адреса
- для того, чтобы убедиться, что сообщение пришло адресату нужного типа
- для формирования ответного сообщения
- для вызова метода exec с параметром нужного типа
Что НЕ верно для AccountService?
- хранит id пользовательских сессий
- метод run() этого объекта запущен в отдельном потоке
- может произвести аутентификацию пользователя и найти его id по имени
- объект, в котором jetty вызывает handle(...) при открытии страниц сервера пользователем
Постановка задачи
Написать приложение, которое обрабатывает запросы из браузера.
При первом запросе страницы приложение создает для пользователя Integer sessionId и объект userSession и добавляет эти объекты в Map<Integer, UserSession> sessionIdToUserSession, после чего возвращает пользователю страницу с sessionId, а так же запрос "Введите свое имя".
Вместе с именем приложение получает от пользователя ранее переданный ему sessionId, находит по этому Id объект пользовательской сессии и записывает в него присланное имя.
После изменения объекта userSession приложение отправляет пользователю страницу с sessionId и статусом "Ждите авторизации".
После отправки страницы приложение запрашивает у службы AccountService аутентификацию пользователя. Служба AccountService работает в отдельном потоке и может найти userId по имени пользователя (поиск может быть долгим, имитацию долгого поиска можно сделать через Thread.sleep(5000)).
Если пользователь запрашивает страницу раньше, чем AccountService нашел userId по имени, он получает страницу с sessionId и статусом "Ждите авторизации".
Если AccountService нашел userId, Frontend должен добавить userId в объект userSession соответствующего пользователя.
При следующем обращении пользователь получит страницу "Здравствуйте: " + userName + " ваш userId: " + userId;
При старте приложение должно создавать два потока: Frontend и AccountService. Frontend должен отвечать на запросы пользователя из браузера, а AccountService обрабатывать запрос на авторизацию. "Общение" между потоками должно проходить через систему обмена сообщениями.