Java осень 2013 лекция 3
-
Upload
technopark -
Category
Education
-
view
189 -
download
3
Transcript of Java осень 2013 лекция 3
![Page 1: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/1.jpg)
Углубленное программирование
на JavaЛекция 3
«Message System»
Виталий Чибриков
![Page 2: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/2.jpg)
1. Frontend и Account Service
2. Concurrent Collections
3. Message System
План лекции
2
![Page 3: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/3.jpg)
UserSession
3
UserSession содержит:
Каждому, кто пришел на сервер - UserSession
Каждой UserSession – sessionId (из HttpSession)
String sessionId
String userName
Long userId
На Frontend-е
Map<String, UserSession> sessionIdToSession;
![Page 4: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/4.jpg)
В одном потоке
4
Назначаем Id для пользовательской сесcии
В методе handle() спрашиваем у Accounter userId по имени
Создаем объект Accounter, который будет скрывать авторизацию
Ждем пока Accounter прочитает эти данные из файла или базы
Создаем на основе сесcии страницу и отдаем ее браузеру
Сохраняем в объекте сессии данные о пользователе
Спрашиваем у пользователя имя
Авторизация
![Page 5: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/5.jpg)
Временная диаграмма
Авторизация
5
![Page 6: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/6.jpg)
Frontend и Account Service
6
Frontend создает пользовательскую сессию
Frontend возвращает страницу созданную на основе сесcии в браузер
Frontend запрашивает у Account Service данные по авторизации
Когда данные приходят, Frontend меняет состояние сессии
Разведем работу с пользователем и Accounter по разным потокам
Frontend ― поток который работает с пользователями
Account Service ― поток который работает с авторизацией
![Page 7: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/7.jpg)
Состояния
7
Ответ 2: sessionId + «Ждите авторизации»
Запрос 0: Первый запрос страницы.
Запрос 2: sessionId
Запрос 3: sessionId
Ответ 3: sessionId + «Ваше имя» + userName + « ваш Id: » + userId
Ответ 0: sessionId + «Введите имя»
Запрос 1: sessionId + Имя
Ответ 1: sessionId + «Ждите авторизации»Запрос на AccountServer
Ответ не пришел
Ответ пришел
![Page 8: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/8.jpg)
Frontend и Account Service
Решение в 2 потока
8
![Page 9: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/9.jpg)
1. Frontend и Account Service
2. Concurrent Collections
3. Message System
План лекции
9
![Page 10: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/10.jpg)
Atomic
10
java.util.concurrent.atomic
AtomicBoolean
AtomicInteger
AtomicLong
Реализованы без использования synchronized
public final int incrementAndGet() {while (true) {
int current = get(); //get() возвращает текущее значение (volatile)int next = current + 1;if (compareAndSet(current, next))
return next;}
}public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
optimistic locking
![Page 11: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/11.jpg)
Synchronized vs. Concurrent
11
Concurrent ― предназначена для работы с несколькими потоками,но не синхронная (без использования synchronized)
ConcurrentHashMap ― concurrent
java.util.Hashtable ― synchronized
synchronized ― гарантия, что только один поток работает с элементом
Concurrent ― разрешено одновременное чтение и безопасная запись
![Page 12: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/12.jpg)
Concurrent Collections
12
CopyOnWriteArrayList копирование при вставке в ArrayList
CopyOnWriteArraySet Set интерфейс над CopyOnWriteArrayList
ConcurrentHashMap thread safe HashMap
ConcurrentSkipListMap ключи уникальны и отсортированы
ConcurrentSkipListSet set на базе ConcurrentSkipListMap
Контейнеры безопасные для многопоточного доступа
![Page 13: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/13.jpg)
Очереди безопасные для многопоточного доступа
Concurrent Queues
13
BlockingQueue очередь с ограничениме размера
ConcurrentLinkedQueue thread safe очередь
LinkedBlockingQueue
ArrayBlockingQueue
BlockingDeque двухсторонняя «очередь»
ArrayBlockingDeque
![Page 14: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/14.jpg)
1. Frontend и Account Service
2. Concurrent Collections
3. Message System
План лекции
14
![Page 15: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/15.jpg)
Thread-local объекты
Основная идея
Обмен сообщениями
15
Один поток кладет сообщение в коллекцию
Второй поток достает сообщение и исполняет его
Thread-Safe коллекции
Безопасная работа с элементами коллекции
Оптимальная работа
Объекты на которые есть ссылки только из одного потока
![Page 16: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/16.jpg)
MessageSystem ―объект для обмена данными
Message System
16
Одна система сообщений на процесс
Единственный объект доступный из нескольких потоков
По одной очереди сообщений на поток
Каждый поток берет свою очередь из потока и выполняет сообщения
Каждый поток имеет свой адрес
Из любого места потока можно положить сообщение в очередь по адресу
![Page 17: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/17.jpg)
Обмен сообщениями
17
FrontendAccount Service
Account Queue
Frontend Queue
MsgToAccountService MsgToFrontend
MessageSystem
![Page 18: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/18.jpg)
Address и Abonent
18
public class Address {static private AtomicInteger abonentIdCreator = new AtomicInteger();final private int abonentId;
public Address(){this.abonentId = abonentIdCreator.incrementAndGet();
}
public int hashCode() {return abonentId;
}}
public interface Abonent {Address getAddress();
}
![Page 19: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/19.jpg)
Message
19
public abstract class Msg {final private Address from;final private Address to;
public Msg(Address from, Address to){this.from = from;this.to = to;
}
protected Address getFrom(){return from;
}
protected Address getTo(){return to;
}
public abstract void exec(Abonent abonent);}
![Page 20: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/20.jpg)
Message to Account Service
20
public abstract class MsgToAS extends Msg{
public MsgToAS(Address from, Address to) {super(from, to);
}
void exec(Abonent abonent) {if(abonent instanceof AccountService){
exec((AccountService) abonent);}
}
abstract void exec(AccountService accountService);}
![Page 21: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/21.jpg)
Message to Account Service
21
public class MsgGetUserId extends MsgToAS {private String name;private String sessionId;
public MsgGetUserId(Address from, Address to, String name, String sessionId) {super(from, to);this.name= name;this.sessionId = sessionId;
}
void exec(AccountService accountService) {Long id = accountService.getUserId(name);Msg back = new MsgUpdateUserId(getTo(), getFrom(), sessionId, id);accountService.getMessageSystem(). sendMessage(back);
}}
![Page 22: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/22.jpg)
Иерархия сообщений
22
Msg
MsgToAS MsgToFrontend
MsgUpdateUserIdMsgGetUserId
- Address from
- Address to
- String name
- Integer sessionId
- Integer sessionId
- Integer userId
![Page 23: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/23.jpg)
Message System
23
private Map<Address, ConcurrentLinkedQueue<Msg>> messages = new HashMap<Address, ConcurrentLinkedQueue<Msg>>();
public void sendMessage(Msg message){Queue<Msg> messageQueue = messages.get(message.getTo());messageQueue.add(message);
}
public void execForAbonent(Abonent abonent) {Queue<Msg> messageQueue = messages.get(abonent.getAddress());while(!messageQueue.isEmpty()){
Msg message = messageQueue.poll();message.exec(abonent);
}}
![Page 24: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/24.jpg)
MessageSystem ничего не знает о Frontend и AccountService
Все что нужно MessageSystem это Address, Abonent и Msg
Можно добавлять дополнительные сервисы
Абстракция
24
![Page 25: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/25.jpg)
Address Service
25
Часть Message System которая знает адреса абонентов
Может вернуть адрес Account сервиса и Frontend
Производит балансировку, если сервисов несколько
![Page 26: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/26.jpg)
Address Service
26
public class AddressService {private Address accountService;
public Address getAccountService() {return accountService;
}
public void setAccountService(Address accountService) {this.accountService = accountService;
}}
AddressService можно хранить в MessageSystem
Address аккаунт сервера для пользователя можно хранить в UserSession
![Page 27: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/27.jpg)
Обмен сообщениями
27
![Page 28: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/28.jpg)
Метод run()
28
public void run() {while (true) {messageSystem.execForAbonent(this);
Thread.sleep(TICK_TIME);}
}
![Page 29: Java осень 2013 лекция 3](https://reader034.fdocument.pub/reader034/viewer/2022052311/559827041a28abe5488b48a1/html5/thumbnails/29.jpg)
Демонстрация кода
29
Переключаемся на код и смотрим как он работает