-
Notifications
You must be signed in to change notification settings - Fork 0
/
Concurrency.drawio
709 lines (709 loc) · 163 KB
/
Concurrency.drawio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
<mxfile host="app.diagrams.net" modified="2021-03-05T09:10:26.732Z" agent="5.0 (Windows)" etag="KnMo-RPUSPdrApQ0M4vp" version="14.2.9" type="github">
<diagram id="dARw1I-tyCDDxnHPdXPz" name="Page-1">
<mxGraphModel dx="3702" dy="3014" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-76" value="" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-2080" y="-1476" width="590" height="271" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-68" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="640" width="540" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-65" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="540" width="540" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-54" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="130" width="540" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-48" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-108" width="540" height="118" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-45" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-236" width="540" height="36" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-42" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-450" width="540" height="144" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-39" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-600" width="540" height="100" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-34" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-880" width="540" height="90" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-27" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="-1335" width="540" height="125" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-8" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-140" y="-1310" width="440" height="65" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-83" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="3200" width="420" height="210" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-80" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="2820" width="330" height="220" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-78" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="2530" width="285" height="150" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-65" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="35" y="2130" width="585" height="250" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-57" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="1824" width="390" height="190" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-49" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="1565" width="360" height="150" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-43" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="30" y="660" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-40" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="1100" width="370" height="181" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-33" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="30" y="120" width="660" height="70" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-26" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FF8000;align=left;" parent="1" vertex="1">
<mxGeometry x="30" y="510" width="660" height="60" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-12" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="30" y="400" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-1" value="<font style="font-size: 18px">4. Компоновка объектов</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="20" y="30" width="220" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-3" value="<div align="left"><b>Проектирование потокобезопасного класса:</b> <br></div><div align="left">1. идентификация переменных, формирующих состояние объекта.<br></div><div align="left"><font color="#FF8000"><font color="#000000">2. идентификация инвариантов, ограничивающих переменные состояния и постусловий.&nbsp;</font> </font><br></div><div align="left">3. создание политики для управления конкурентным доступом к состоянию объекта.<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="124" width="520" height="60" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-4" value="Политики синхронизации (synchronization policy). (рекомендуется документировать. @GuardedBy("this")" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="200" width="600" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-5" value="<div>Примитивные переменные содержат все состояние объекта, <br></div><div>ссылочные включают в себя другие объекты влияющие на потокобезопасность</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="230" width="470" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-6" value="<div>final уменьшает пространство состояний переменных. (state space) <br></div><div><b>Инварианты</b>: различают valid и invalid состояния. (Long.MIN_VALUE - Long.MAX_VALUE valid)</div><div><b>Постусловия</b>: 17 -&gt; 18 -&gt; 19 -&gt; 20 (допустимые переходы состояний)</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="320" width="540" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-7" value="<div align="left"><b>Обеспечивайте потокобезопасность, учитывая роль инвариантов и постусловий.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="370" width="490" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-15" value="<font style="font-size: 14px">4.1.2. Операции зависимые от состояния<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="405" width="290" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-17" value="<div align="left">Методы с предусловиями основанными на состоянии. (<b>state-dependent</b> методы. Проверяющие что очередь <br></div><div align="left">пустая а значит с нее нельзя удалять объекты) <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="445" width="630" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-18" value="Если предусловие не соблюдается: " style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="200" y="480" width="220" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-19" value="<b><font color="#00CC00">One thread: </font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="510" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-20" value="<b><font color="#007FFF">Multithreading: </font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="340" y="510" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-21" value="Операция завершается безрезультатно." style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="530" width="250" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-22" value="<div>Ожидает появления потока принимающий имеющееся <br></div><div>условие для продолжения работы.<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="340" y="532" width="330" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-23" value="<div align="left"><b>wait()</b> и <b>notify()</b> сложны в применении по этому вместо них используются библиотечные классы, такие как <br></div><div align="left"><b>блокирующие очереди</b> или <b>семафоры</b>. <br></div><div align="left">Блокирующие библиотечные классы (<b>BlockingQueue</b>, <b>Semaphore </b>и другие синхронизаторы) </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="580" width="620" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-27" value="" style="endArrow=none;html=1;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="309.66" y="570" as="sourcePoint" />
<mxPoint x="310" y="510" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-28" value="<div align="left"><b>Объект владеет состоянием которое инкапсулирует</b> и отвечает за управление многопоточным доступом.<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="700" width="620" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-29" value="<div><b>Объект не владеет состоянием объектов передаваемых в методы</b> если только он не предназначен для</div><div>передачи права владения.<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="730" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-30" value="<div><b>Коллекционные классы часто демонстрируют форму раздельного владения</b>: они владеют состоянием <br></div><div>коллекции, но хранящиеся у себя объекты передают клиентскому коду</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="770" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-34" value="<div><b>Непотокобезопасный </b>объект можно использовать безопасно с о<b>граничением одним потоком</b> или <br></div><div><b>блокировкой</b>. </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="867" width="580" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-36" value="<div><b>Инкапсуляция </b>упрощает создание потокобезопасных классов, обеспечивая <br></div><div><b>ограничение одним экземпляром</b> (instance confinement), которое часто называется <b>запиранием </b>(confinement).</div><div style="font-size: 11px"><font style="font-size: 11px"><i>Объект инкапсулируется в другой объект, к которому имеют доступ только некоторые <br></i></font></div><div style="font-size: 11px"><font style="font-size: 11px"><i>известные ветви кода, а не вся программа</i></font><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="900" width="650" height="60" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-37" value="<div><b>Инкапсуляция данных в объекте ограничивает доступ к ним только методами объекта, что упрощает <br></b></div><div><b>обеспечение постоянного доступа с удержанием замка.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="970" width="610" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-38" value="<div align="left">Ограниченные экземпляром объекты не должны выходить за пределы своей области действия. <br></div><div align="left">Объект может быть ограничен <b>экземпляром класса </b>(например, приватным членом класса), <br></div><div align="left"><b>лексической областью</b> (например, локальной переменной) или <br></div><div align="left"><b>потоком </b>(например, объектом, который передается из метода в метод внутри одного потока). <br></div><div align="left"><b>Публикуйте объекты осторожно.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1010" width="570" height="80" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-39" value="<div align="left">@ThreadSafe<br>public class PersonSet {<br>&nbsp;&nbsp;&nbsp;&nbsp; @GuardedBy("this")<br>&nbsp;&nbsp;&nbsp;&nbsp; private final Set&lt;Person&gt; mySet = new HashSet&lt;Person&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void addPerson(Person p) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySet.add(p);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public synchronized boolean containsPerson(Person p) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mySet.contains(p);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="1110" width="360" height="160" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-41" value="<div align="left"><b>ArrayList </b>и <b>HashMap</b>, не-потокобезопасны, но их можно использовать в многопоточных средах. <b>Оберточные <br></b></div><div align="left"><b>фабричные методы</b> (Collections.<b>synchronizedList </b>и др.) с помощью паттерна <b>декоратора</b>обертывают коллекции <br></div><div align="left">синхронизированными объектами, заставляя методы интерфейса пересылать запросы базовым коллекционным <br></div><div align="left">объектам</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1295" width="670" height="60" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-42" value="<div align="left"><b>Ограничение одним экземпляром упрощает создание потокобезопасных классов, позволяя анализировать их <br></b></div><div align="left"><b>потокобезопасность без проверки всей программы.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1365" width="670" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-44" value="<font style="font-size: 14px">4.1.3. Владение состоянием<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="665" width="200" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-45" value="<div align="left">По принципу <b>ограничения одним экземпляром</b> работает и <b>мониторный шаблон Java. <br></b></div><div align="left"><b>(Java monitor pattern (Hoare, 1974)</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1460" width="510" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-46" value="Монитор используется также библиотечными классами <b>Vector </b>и <b>HashTable</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="30" y="1495" width="450" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-47" value="<div align="left">Вместо монитора можно использовать <b>приватный замок</b>, который благодаря <b>инкапсуляции </b>не позволяет <br></div><div align="left">захватить себя извне избавляя от необходимости проверки всей программы. <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1520" width="630" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-48" value="<div align="left">public class PrivateLock {<br>&nbsp;&nbsp;&nbsp;&nbsp; private final Object myLock = new Object();<br>&nbsp;&nbsp;&nbsp;&nbsp; @GuardedBy("myLock") Widget widget;<br>&nbsp;&nbsp;&nbsp;&nbsp; void someMethod() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(myLock) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Обратиться и изменить состояние виджета<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="60" y="1575" width="320" height="130" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-53" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="40" y="830" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-54" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-53" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-55" value="<b><font style="font-size: 14px">4.2. Ограничение одним экземпляром<br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-53" vertex="1">
<mxGeometry x="10" y="5" width="290" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-56" value="<div align="left">@ThreadSafe<br>public class CountingFactorizer implements Servlet {<br>&nbsp;&nbsp;&nbsp;&nbsp; private final AtomicLong count = new AtomicLong(0);<br>&nbsp;&nbsp;&nbsp;&nbsp; public long getCount() { return count.get(); }<br>&nbsp;&nbsp;&nbsp;&nbsp; <br></div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp; public void service(ServletRequest req, ServletResponse resp) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BigInteger i = extractFromRequest(req);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BigInteger[] factors = factor(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count.incrementAndGet();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encodeIntoResponse(resp, factors);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="1835" width="380" height="170" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-58" value="<div align="left">Мы добавили <b>AtomicLong </b>в объект, который не всегда поддерживал внутреннее состояние, и результирующий <br></div><div align="left"><b>композитный </b>объект стал потокобезопасным.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1785" width="640" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-59" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="1410" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-24" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="QMmgmNxQZZJa730i63d_-59" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-25" value="<font style="font-size: 14px">4.2.1. Мониторный шаблон Java<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-59" vertex="1">
<mxGeometry x="10" y="5" width="230" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-63" value="<div align="left"><b>Делегировать </b>потокобезопасность более чем одной базовой переменной состояния возможно, если эти <br></div><div align="left">переменные <b>независимы</b>, то есть композитный класс не накладывает инварианты с их участием.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="2085" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-64" value="<div align="left">public class VisualComponent {<br>&nbsp;&nbsp;&nbsp;&nbsp; private final List&lt;KeyListener&gt; keyListeners = new CopyOnWriteArrayList&lt;KeyListener&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp; private final List&lt;MouseListener&gt; mouseListeners = new CopyOnWriteArrayList&lt;MouseListener&gt;();</div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp; public void addKeyListener(KeyListener listener) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyListeners.add(listener);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public void addMouseListener(MouseListener listener) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; mouseListeners.add(listener);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public void removeKeyListener(KeyListener listener) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; keyListeners.remove(listener);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public void removeMouseListener(MouseListener listener) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; mouseListeners.remove(listener);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="2140" width="570" height="230" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-66" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="1739" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-31" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-66" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-32" value="<b><font style="font-size: 14px">4.3. Делегирование потокобезопасности<br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-66" vertex="1">
<mxGeometry x="10" y="5" width="310" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-67" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="2400" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-68" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-67" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-69" value="<b><font style="font-size: 14px">4.4. Добавление функциональности в существующие потокобезопасные классы<br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-67" vertex="1">
<mxGeometry x="10" y="5" width="590" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-70" value="<div align="left">Мы можем <b>расширять существующие потокобезопасные классы</b>. <br></div><div align="left">Но это определенная зависимость от родителя. если его замок измениться, но у наследника будет <br></div><div align="left"><b>неправильный замок</b>. </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="2440" width="580" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-71" value="<div align="left"><b>Лучше использовать готовые инструменты многопоточности</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="2500" width="370" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-72" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="2040" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-61" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="QMmgmNxQZZJa730i63d_-72" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-62" value="<font style="font-size: 14px">4.3.2. Независимые переменные состояния<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-72" vertex="1">
<mxGeometry x="10" y="5" width="310" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-73" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="2710" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-74" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="QMmgmNxQZZJa730i63d_-73" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-75" value="<font style="font-size: 14px">4.4.1. Блокировка на стороне клиента<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-73" vertex="1">
<mxGeometry x="10" y="5" width="270" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-76" value="<div align="left">Блокировка на стороне клиента (<b>client-side locking</b>) или <b>внешняя блокировка</b> может решить проблему <br></div><div align="left">расширения синхронизированного класса <b>ArrayList </b>в обертке <b>synchronizedList</b>, где у нас нет доступа к <br></div><div align="left">внутреннему объекту. <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="2760" width="610" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-77" value="<div align="left">@ThreadSafe<br>public class BetterVector&lt;E&gt; extends Vector&lt;E&gt; {<br>&nbsp;&nbsp;&nbsp;&nbsp; public synchronized boolean putIfAbsent(E x) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; boolean absent = !contains(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if (absent)<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; add(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return absent;<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="2540" width="280" height="130" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-79" value="<div align="left">@ThreadSafe<br>public class ListHelper&lt;E&gt; {<br>&nbsp;&nbsp;&nbsp;&nbsp; public List&lt;E&gt; list =<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Collections.synchronizedList(new ArrayList&lt;E&gt;());<br>&nbsp;&nbsp;&nbsp;&nbsp; ...<br>&nbsp;&nbsp;&nbsp;&nbsp; public boolean putIfAbsent(E x) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; synchronized (list) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; boolean absent = !list.contains(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if (absent)<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; list.add(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return absent;<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="2830" width="320" height="200" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-81" value="<div align="left">В то время как расширение класса<b> нарушает инкапсуляцию реализации</b>, блокировка на стороне клиента <br></div><div align="left"><b>нарушает инкапсуляцию политики синхронизации</b>.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="3050" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-82" value="<div align="left">@ThreadSafe</div><div align="left">public class ImprovedList&lt;T&gt; implements List&lt;T&gt; {<br>&nbsp;&nbsp;&nbsp;&nbsp; private final List&lt;T&gt; list;</div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp; public ImprovedList(List&lt;T&gt; list) { this.list = list; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public synchronized boolean putIfAbsent(T x) {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; boolean contains = list.contains(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if (contains)<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; list.add(x);<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return !contains;<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void clear() { list.clear(); }<br>&nbsp;&nbsp;&nbsp;&nbsp; // ... делегировать остальные списковые методы схожим образом<br>}<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="50" y="3208" width="400" height="190" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-84" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="3100" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-85" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="QMmgmNxQZZJa730i63d_-84" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-86" value="<font style="font-size: 14px">4.4.2. Компоновка<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-84" vertex="1">
<mxGeometry x="10" y="5" width="130" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-87" value="<div align="left"><b>Добавить атомарную операцию</b> в существующий класс поможет <b>компоновка </b>(composition). Класс <i>ImprovedList </i><br></div><div align="left">реализует списковые операции, передавая их в базовый экземпляр <i>List </i>и добавляя атомарный метод <br></div><div align="left"><i>putIfAbsent</i>, через который клиент должен обращаться к базовому списку.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="3140" width="650" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-88" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="3430" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-89" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-88" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-90" value="<b><font style="font-size: 14px">4.5. Документирование политик синхронизации<font style="font-size: 14px"><br></font></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-88" vertex="1">
<mxGeometry x="10" y="5" width="360" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-91" value="<div align="left"><b>Документируйте гарантии потокобезопасности класса</b> для клиентов и политику синхронизации — <br></div><div align="left">для сопроводителей.</div><div align="left">Каждое применение механизмов <b>synchronized</b>, <b>volatile </b>или любого потокобезопасного класса отражает <br></div><div align="left"><b>политику синхронизации</b>. Как проектный элемент программы она должна быть задокументирована, <br></div><div align="left">причем лучше всего — на этапе разработки.<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="3470" width="610" height="80" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-95" value="Проектирование потокобезопасного класса содержит следующие шаги: <br><b>1. Найти переменные формирующие состояние объекта. <br>2. Найти инварианты и постусловия которые могут повлиять на состояние объекта. <br>3. Создать политику для управления конкурентным доступом к состоянию объекта.</b> <br><div><br></div><div><b>Ограниченные одним экземпляром классы</b> (singleton) и <b>инкапсуляция </b>значительно упрощают работу с </div><div>многопоточными программами.</div><div><b>Монитор </b>может быть полезен для работы с многопоточностью, но это очень базовый инструмент и не <br></div><div>самый продвинутый. </div><br><div>Мы можем <b>делегировать </b>обеспечение потокобезопасности <b>потокобезопасным объектам</b>.</div><div>Их может быть даже несколько. </div><br><div>Мы можем <b>расширять потокобезопасные классы</b> добавляя в них новый функционал и он будет <br></div><div>потокобезопасным, но это влечет за собой <b>уязвимости</b>. Также как и <b>внешняя блокировка</b>. <br></div><div><b>Компоновка </b>гарантированно обеспечит потокобезопасность но вероятно наложит <b>ограничения <br></b></div><div><b>на производительность</b>. </div><br><div>Все эти интересные подходы нужно <b>документировать </b>иначе малейшие изменения могут создать <br></div><div>трудноуловимые баги.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="3630" width="610" height="290" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-93" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="30" y="3580" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-94" value="<font style="font-size: 14px"><b>Summary</b></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="40" y="3585" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-96" value="<font style="font-size: 18px">5. Строительные блоки<br></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="870" y="30" width="210" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-97" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="70" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-8" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-97" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-10" value="<b><font style="font-size: 14px">5.1. Синхронизированные коллекции <br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-97" vertex="1">
<mxGeometry x="10" y="5" width="280" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-98" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="70" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-99" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="QMmgmNxQZZJa730i63d_-98" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-100" value="<b><font style="font-size: 14px">4.1. Проектирование потокобезопасного класса<br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-98" vertex="1">
<mxGeometry x="10" y="5" width="360" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-101" value="<div align="left">Синхронизированные классы коллекций: </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="110" width="250" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-102" value="<b>Vector, Hashtable, Collections.synchronized****</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="130" width="280" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-103" value="<div><b>Инкапсулируют состояние </b>и <b>синхронизируют </b>каждый публичный метод, позволяя только одному потоку <br></div><div>обратиться к коллекции<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="150" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-104" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="30" y="280" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-16" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="QMmgmNxQZZJa730i63d_-104" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-11" value="<font style="font-size: 14px">4.1.1. Сбор требований к синхронизации<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-104" vertex="1">
<mxGeometry x="10" y="5" width="290" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-105" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="200" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-106" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="QMmgmNxQZZJa730i63d_-105" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-107" value="<font style="font-size: 14px">5.1.1. Проблемы синхронизированных коллекций<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-105" vertex="1">
<mxGeometry x="10" y="5" width="340" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-108" value="<div align="left">Поскольку синхронизированные коллекции поддерживают блокировку на стороне клиента, существует <br></div><div align="left">возможность создания новых операций, атомарных по отношению к другим операциям над коллекцией, <br></div><div align="left">если известен замок.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="240" width="620" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-110" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,iVBORw0KGgoAAAANSUhEUgAAA7cAAAEUCAYAAADwc8FqAAAgAElEQVR4nO3d/3MU953n8f1PRqc2KptSFiyhNUUwnF0Ua6tsyqZsLTFnQxabbxubXBaTWyS7ziS1BtYGVyLhREksZW05BfhqlMQoZ0iQE2wifBZG2pUWhkQxliLFKMjgCUyMYF73w0yPZnp6WtPz0Ug9w/NR1VWJJaSZjz6fnver+/P59N8IAAAAAIAS9zdz/QIAAAAAADBFuAUAAAAAlDzCLQAAAACg5BFuAQAAAAAlj3ALAAAAACh5hFsAAAAAQMkj3AIAAAAASh7hFgAAAABQ8gi3AAAAAICSR7gFAAAAAJQ8wi0AAAAAoOQRbgEAAAAAJY9wCwAAAAAoeYRbAAAAAEDJI9wCAAAAAEoe4RYAAAAAUPIItwAAAACAkke4BQAAAACUPMItAAAAAKDkEW4BAAAAACWPcAsAAAAAKHmEWwAAAABAySPcAgAAAABKHuEWAAAAAFDyCLcAAAAAgJJHuAUAAAAAlDzCLQAAAACg5BFuAQAAAAAlj3ALAAAAACh5hFsAAAAAQMkj3AI+RCIRWaEKDo6Cj8adO+e6GwdWZzg8538fjtI+GF8AcGsj3AI+2OE2EolwcPg+Xj3wKsW3h85wWFu3bJnzvxNHaR6MLwAA4RbwIRJJhFugEJ3hMMW3B9oHJug/AADCLeAD4RYmKL690T4wQf8BABBuAR8ItzBB8e2N9oEJ+g8AgHAL+EC4hQmKb2+0D0zQfwAAhFvAB8ItTFB8e6N9YIL+AwAg3AI+EG5hguLbG+0DE/QfAADhFvCBcAsTFN/eaB+YoP8AAAi3gA+EW5ig+PZG+8AE/QcAQLgFfCDcwgTFtzfaByboPwAAwi3gA+EWJii+vdE+MEH/AQAQbgEfCLcwQfHtjfaBCfoPAIBwC/hAuIUJim9vtA9M0H8AAIRbwAfCLUxQfHujfWCC/gMAINwCPhBuYYLi2xvtAxP0HwAA4RbwgXALExTf3mgfmKD/AAAIt4APhFuYoPj2RvvABP0HAEC4BXwg3MIExbc32gcm6D8AAMIt4APhFiYovr3RPjBB/wEAEG4BHwi3MEHx7Y32gQn6DwCAcAv4QLiFCYpvb7QPTNB/AACEW8AHwi1MUHx7o31ggv4DACDcAj4QbmGC4tsb7QMT9B8AAOEW8IFwCxMU395oH5ig/wAACLeAD4RbmKD49kb7wAT9BwBAuAV8INzCBMW3N9oHJug/AADCLeAD4RYmKL690T4wQf8BABBuAR8ItzBB8e2N9oEJ+g8AgHAL+EC4hQmKb2+0D0zQfwAAhFvAB8ItTFB8e6N9YIL+AwAg3AI+EG5hguLbG+0DE/QfAADhFvCBcAsTFN/eaB+YoP8AAAi3gA+EW5ig+PZG+8AE/QcAQLgFfCDcwgTFtzfaByboPwAAwi3gA+EWJii+vdE+MEH/AQAQbgEfCLcwQfHtjfaBCfoPAIBwC/hAuIUJim9vtA9M0H8AAIRbwAfCLUxQfHujfWCC/gMAmNNwG48Oq7+3V729vertH1Y0PpevBpge4bac3dDlwePqPDaoy7nORfGYxs/3qvvIz3X0vQENRyd9/QaKb2+0z1yJKxb5hQ7sP6jeiRuZX5q8ouGBkzr60y519/5O47Gbmf9yolc/2d+qrkh0Fl+vO/oPAGDuwm18XD17VqsqVCErVCFr8V6dukq6RbARbstYrF+tjy6QtapNkZvZX45Hz6qz6aGpc1aoQlbNJh3oGVW+EZfi2xvtM0cmh9T59HLd1XRcE6mP4bgmR3+tV55YMtXfQxWqum+nDg9e1tS3faruppWq23RIQ9fn9jOc/gMAmKNwG1ds4IdqqKyQ9bd3qrayQlblZh3+5Iu5eTlAngi3ZSr+mfpa1iaCq1u4TV2Mq1b99lfVefxX6vpBox5ZaMmq2abDQ9fy+jUU395on7lwQxPdL+iuyjVq6buS+q/xzz/QKw9WywrN1z0bX9Kh479R98HdWldjyap5Wh3n7Du1cX0x8AM9VLlCz3V/qrmMt/QfAMDchNv4sLqeWSYrZOmu/7VXLz44X1bofu3p+WxOXg6QL8JtGYpf1kD7VtXZd6eywm1c18+1a01lhaoe/aEGYnb5PqmLJ/bogUrLcccrN4pvb7TPHIgP6fC6O1XV0K5I6s7rVUXa1qsqZOmuZ49odNL+73HFzr2pTTXzVPfM2xqNO37GukP6ZA7TLf0HADAH4TZ5lThUIatyvdrP/qcOr7tTVuhOrT80NKdXfYHpEG7LSzz6Ox3d91XVhSpU9eVlWlbpFm7tQt/lztT1QbU3LJC16AV1O9cquqD49kb7zDb7wk2dNocvTPXtL86oZcW8xGf0uauOf/OZTu2+3/G1SV08sl23Vz6m1oG/zN7Ld6D/AABmP9xeO62WB6sTd22bjmsiPq7uxsRd3CW7e+T8GAWCJP9w+1eNR86ot/e8xidvKDb6kY6+2apXWt/U2+9FdHky12Wcm4qNDer9oz/T4bYWvdLaoc6jH2jos+vu3z45och7XTrc9kO1v3VUp4YmHOs/byg6PJDYtK33jCLjf/V4rb3J15v52uKxUfW/+3N1tDartePnerd/VLGsl1/o+51LU+ee2kdfUvfZLjXd4RJuk3elrNu2q+uic3VtVP3Nq/OeeULx7c1f+0zq8lCfR7+2+37m1zM2Msw6Tqt/OOq4yJrvmEwfR7mO9PFlf/+AhqPOCyP2184oMv55Hj/Xfo9eP9NNsv86lgXFLx7RttsqZK1oUf8XzrGbDLKOC9LxTw5pfeU8rWw+o7laYMT4AgDMcri9pqFD2xLT/2q2q/OTmKSYIm1rExtVzPGUJmA6+YfbZHC6Y6fC77dpU42VtimLpbqNr2vAWXzGL2vw0E7VV1ZkbOCS2Lhoq348cDmj6I5H+/XjjUszv6/yYX3r+EhawJ0aX1Zogda0DSorJtt3H0MVsu54Xt1X7GR3Q9GhI9pVX+14PXVq2HM8bapige93zo2ru2mNNn33mIaiN6Qr3e7h9mqP9iy2fBX6uVB8e/MbbhNtn+PCaPyP6np6cdZFiZuRNj3kHF+pY74eajur1J/f15i0L5bk+tnO8WV//1q1R2KZL330bX29xpIVWqam7sHpf25omZq6xz1/piv7Dq2jb6fayHVztZu60v28vuRs95tn1b5qfo5xMjsYXwCAWQ238Ynjem6RJStUrVXNp5XYgsX+oGTHZMy8f/7GN7R1y1Z1hsOKRCLGP893uK1crOVfrlbdhhZ1D17Q6NAHOtz0UGIt2453dDHV3W9ooudlPVBZoar7dqjtaI/6z0U02PuuDiV36K1a9QMNpIrGv2ig9TFVhar1QNNP9N5/DqjvaLOeqrFk1exQ16gdYe1wW63ahfNcLyDdHOrQVyqzi+/4xXf17fpqWZUr9cz3f6FTA4MaOPULtX5tpapC1Vq1/wN9nvpZft9vEHyhy+NXpi4E5Aq3uf67pKnzlyMU5VBuxffSJUvU1NioY8eOaWRkxPjn+W0frzuM9tecfT4R3Gr1+O431BkOJ4+31Lr97x3h1u+YtIPl3+vZ1rfSfnZYnQd36/Hb8g23V9TXvCa5K/cyNXUPa7inK/Wzwq3bdU+oQtby7WpN/Y4unRqOefxMd4mxn31xIHEXdro+X6EvNXZragsqe7ryBnUMud1JL75yG18AAP9mMdymfWBnrE+L64u+Fq0MsWMyZt7WLVuz7nKYhF3f4Tarv2vqTmn6mrX4qI4+u1yW27rO1Pq3tPFh303M+Nn2FNn0u4h2uF2px9fe6zK19gt9cmizqioXqPZvrbTi2x6vC9TQ2q/0MjkePa0Djzpev9/3WzRxXT/37/rqpgLuFOcIsfndxXIW+u7Krfi2x9Ttt82TFapQXW2tUdj13T723dmsvmXv7ZB9Rz3x97TvdNrscZIWbv2OSa9gafetPMLt1F3b9Duyztefqz/6Cbd233WZdeB6frHZ5xlnn0+eS0KLte3IH+dk/4xyG18AAP9mKdxO7TbqNjUydfWdHZMxw9zCrUnY9R9u3aYC29MpF+grHecThfT1YZ16q03Ne99S/zVnWehSsE5GNRY5o/f7/pj2s10K9NR/+4q+0/qcloRWatd7l6Z+dDIcVK3erH+6b/5U8W0X767F7XWNhrc5puL6fL/FZD930+9U6GnCba5lE/bXb+Vw6zwKDbv+28cOVM6+dUnvvbDSJfTaF1PzCLd+x+SMhNvkRaXKh/XM1voih1v7PWf/jsQYWiHL7eJWagaW8zX4m8VQDOU2vgAA/s1OuE09+qdCVQ8eUJ+zULALaXZMxgzLJ9z6Cbv+w+1qtfRFs76afyCaVHTsQ7VvqJu+YE2tnU2/SGQXsGvV/uE72rVoXsYUxMSFpQVa86OD+v6qqXBrT0t0D3RTsy2mXv9Mvd+ZkZhSvSCxUdRonlMkC7pz69YWuZVb8Z3vmMo37BbSPq59NXnnMfPxNtJUAHOOJbcLQ7nkGpPm4TZx13ae7mp6W7/NETzzC7dr1NJzQWNjYxob+7Oirhu6eY3ZtGfR28sS+vp05sRb2vvEUtXevVS1oQrd/vSRjKUGsz3OncptfAEA/JuFcDu1bskKLda61pP6ZGws+aGbPEZPqbVhgdgxGTOtkHDrFXb9r7l1n2qfc03b5ISGeo7qrbZm7Wl8Wo/fV5v2WtzDbXz4iJ7fsCH5vUu1qb1f0VTBmRZuz/0+MYUztT7Rnrq5Wi0ffZDYDOaO59V95cbUUoFpjqlAUeD7zfimmC7/yXFuKPj4WL1tyWfX1nxV+985O/2OzUxL9q3QMZUr7BbUPjfPq+MfFqRNubcvOLjt3GtPw3f2U49wm/eYNA239l3b9Wo/dynnXdX8wq2zzedr+dpGHeg6m3ZumO4u7181evzF5Gd32pivf1G/PN7iGmIJtwCAuVb8cJu+E6uvYhlzxTQM3gpHZzisS5cuebSivXtwejGbJitIxTU5+mu98sSStN9jqfa+J/Vc8/e0e21tziI0c/dX587EaeE2ciVZ2NsbviQ3gFnRov7Y2bRwO5kKbFV3r9aTG57UU7mO545oOD3c5v1+XdjfU5S/2Xyt3PeB94WzWdpQ6p7ly9W4c2dZHDP197mt4r+l/vd/X7ZMx44d07Vr16ZpTZv9HGJ7rae9JtTtjmTya1n91C3c+h2TZuF26q7tcU3Ec08Zzi/cLtHjjXu1f98+7d/dqGf+cbWWV1bICi3Vpo7B5DTjfKYwX9flyLvqaN6jXS/8m1oPvac/RG8kX0P2xWj7tTnv6M4Wwi0AoMjh9rpGj+xI3D2prNczL76c+LDNOl7W7q/VJzabYsdkzKCZuHObfjy+9n/IClXksT7Xu3DMWsd5/bwOb1oqK1St+u0/0tHeiIbHo8mdfPNcRzc5rt7mtarKWPeaHm5jybXvyen/V3u0Z3FymvLNs653bvO/A+Pz/boJ6J3b1OY6rucmf5vodIbDWtPQkLmTbgkfMzGm5lVOPTbq7iVfVv399/vc7M2+U2vprhdO6HP7gqrb38teY57VD93W3Podkybh9tO0u7ZX5bUetrA1tzcVu/Az7Vhkyapp1NGLk96v11Pujai4cwsAmGtFDbdTG09YyavROb9TV3v2akmogh2TMaNMw61z/e3MrLm1+/vUnY/UtN17X1Gvc026vSOsswidvKpoLLO6zX78SWa4tde33/702xrpa9FKe31uRri9Oe004vhfxjUy9pliWVMc83u/xRa/+I6+uWie6p74jk4YrrlVfEiH192Z49yUvPudY62xU7kV34WMKXtKshWq0LZnnskYXwW3j71vw+K9+u3Zg1rv8ngbSdLnJ7LWnSdkh1v/Y7LwcPva8YNpd23TX89Mbihl91V7Tb7z/6e/v6iG+0+r99Sg/pR1UShXn5/9ce5UbuMLAOBfEcNt2qN/arbp8JD3FLNUIcGOyZhBfsPtdDsnz8xuyVfUu+8hWam7fVMXd9zueExdJLIL1kld7H5RDyyszd6ALSugOcKtXZgu2q7ml9aqyt4N2RFuvR/fY++WnL6m0c/7LbIZ3i15atprnTaHL2S+/msfav+98/KecVJuxbdpmHUqvH3sqcgP6l8av6rbnbuCS5oKXy6P9skKt37HpFR4uF2i+vvqHGOtGOHW/pr9Geu1W7L9iKXsCzqp957V59ktGQAw94oUbuOa/CSsbTWWrFC1VjWf1rSrp+ypf+yYjBk0Xbj1+8zbgp5zm3Fx54aiA69rU03mMySn7hK9pFOfpwWyyYvq2deQuEiUdqcktUNs/cvqST2qx94gKn3NmzPc2o/lqVbtwnlT3+cMt6lA51zDG9fk6C/1rfpqWZVr1NJnl/3+3m/xxHWt74Aeavie+mboObfpjzLLbO9rGjq0TXWheVqx78Ppz3Eqv+LbNMw6Fd4+dhidp9qF1e59zX68jWs/9Lpzm9+YTI2hrGdJa5pwW+Eyu2mGw208pou9bYlxmJqWbLeZWxi1p9tXa9X+D/S5/brin6mvxbn0wfma5+4CdbmNLwCAf8UJt6ln5FXkX9DaU//YMRkzyBlu/YZZJ//h9k4tv/tOWQsf1Y7mf1dH8w49stCSVfmwvn3iT1MXcVLr+yzVPfGiOsJhdR76kXZvWKGqmnV6duvKzEI3Pq6ePatVFapQ1X1fV3PHWzrc2pj82au1t2c8+bOd4Tb9udJpd1Kzwq2k2KA6NiZeU+3q7drfdlCH2/5VTy2fLytUrQf2vJ9WjPt8v0HktXFU/LIG2hNreKuWb9Tu19rU+sKTuqeyQtaipmRYmF65Fd+JNbOVBYdZJ6P2SV0gddnQ6GqvWjclN1VaeL8ez9oczd5t3FLtfY9pS2uvruY7Jn/1/9T13DrVL0yuHXa7iz9duM2a3WQabmtVv3ZD8r2t1yN3z0/+jZZq86HzqVBqnwvcNoCKT7yvvfXVskJ1euTZ76jjYPK9Z13wsv9B7ru9s6XcxhcAwL+ihNtrfQe0qrJCVmiZtoWHlF/ZZ6/jYcdkzJzXXnvNqNh28h9uH1Nr9y/V+rWVyTs9FapavkUtJ0Yc4yKuybGTGd9nhebrno3f1dGhK6m7Uul3COPR8+ra/Zhq0++cLXxMe7vTf3Z2uHVdQ+oWbiXFo2fVtW9zIsSlfkeDmtp7NJaxFs/v+w2g6XZ0nvyz+t74RlpbWKp99Nv66bkreYf2ciu+v7ljx4yOL7P2uaT3XljpPv3d507cianIeY7JvT/Qd1bNT/X1Az3OKc+aJty6zW4yDbfO91Sr+g3fUvu7v097FJCmzgWu0+rjmhz9jVo2rkh7/3Vq2PUzRdxmRdjPFp7Dz+9yG18AAP9m4Tm3QPnwH26ToTIe0/j5fp0evKCJmMdqtHhMEx8P6nRvvyJj0TwC4U3FJi5osLd3+p9dsJuKfTaiSN9pnR78WBejbq+qwPdbcuKajI4p0nda/ZExRafbgdmB4tubUfvYM4ZyTgvOYy1o8iJPxjpb32OylNjr5z02REu9/0F9PBHLcSHH3rF6bpcVMb4AAIRbwIeCw23Zu9Xeb2Eovr0Ztc/nJ7RrUY47hybhtszFL76jHTXz0zaHK0RyQ6+aHeoavT79txcJ4wsAQLgFfCDc5nKrvd/CUHx7K7x9YvokvF11bjtaS4RbT8klQW6PPMrXtQ+1/9750zzyr/gYXwAAwi3gA+E2l1vt/RaG4tub7/a5GdHhrz+pp9ben1h7nmsDw6u9at28Wc8fcQm+6eIX1PXc5sSGUn5ffMmydwN3e0RSPpK7tLs+Nmx2Mb4AAIRbwAfCbS632vstDMW3N9/tY+/QG6qQVfmwvnW8BDYuC6L4hHr3N+j2hnZFrvuMt9cH1d6w2LF7+txgfAEACLeAD/mH25uKffapxsb+7HvTodJ0q73fwlB8e/PfPjcVGzur070f6b/Grgb7UVMBF48Oq793QMN+nw8dG9NgIf+uCBhfAADCLeBD/uEWyEbx7Y32gQn6DwCAcAv4QLiFCYpvb7QPTNB/AACEW8AHwi1MUHx7o31ggv4DACDcAj4QbmGC4tsb7QMT9B8AAOEW8IFwCxMU395oH5ig/wAACLeAD4RbmKD49kb7wAT9BwBAuAV8INzCBMW3N9oHJug/AADCLeAD4RYmKL690T4wQf8BABBuAR8ItzBB8e2N9oEJ+g8AgHAL+EC4hQmKb2+0D0zQfwAAhFvAB8ItTFB8e6N9YIL+AwAg3AI+EG5hguLbG+0DE/QfAADhFvCBcAsTFN/eaB+YoP8AAAi3gA+EW5ig+PZG+8AE/QcAQLgFfCDcwgTFtzfaByboPwAAwi3gA+EWJii+vdE+MEH/AQAQbgEfCLcwQfHtjfaBCfoPAIBwC/hAuIUJim9vtA9M0H8AAIRbwAfCLUxQfHujfWCC/gMAINwCPhBuYYLi2xvtAxP0HwAA4RbwgXALExTf3mgfmKD/AAAIt4APhFuYoPj2RvvABP0HAEC4BXwg3MIExbc32gcm6D8AAMIt4APhFiYovr3RPjBB/wEAEG4BHwi3MEHx7Y32gQn6DwCAcAv4QLiFCYpvb7QPTNB/AACEW8AHwi1MUHx7o31ggv4DACDcAj4QbmGC4tsb7QMT9B8AAOEW8IFwCxMU395oH5ig/wAACLeAD4RbmKD49kb7wAT9BwBAuAV8INzCBMW3N9oHJug/AADCLeAD4RYmKL690T4wQf8BABBuAR8ItzBB8e2N9oEJ+g8AgHAL+EC4hQmKb2+0D0zQfwAAhFvAB8ItTFB8e6N9YIL+AwAg3AI+EG5hguLbG+0DE/QfAADhFvCBcAsTFN/eaB+YoP8AAAi3gA+EW5ig+PZG+8AE/QcAQLgFfLDDbSQS4eDwfbx64FWKbw+d4bC2btky538njtI8GF8AAMIt4EMkkgi3HByFHhTfuXWGw3P+9+Eo7YPxBQC3NsItAAAAAKDkEW4BAAAAACWPcAsAAAAAKHmEWwAAAABAySPcAgAAAABKHuEWAAAAAFDyCLcAAAAAgJJHuAUAAAAAlDzCLQAAAACg5BFuAQAAAAAlj3ALAAAAACh5hFsAAAAAQMkj3AIAAAAASh7hFgAAAABQ8gi3AAAAAICSR7gFAAAAAJQ8wi0AAAAAoOQRbgEAAAAAJY9wCwAAAAAoeYRbwIeRkRE17tzJwVHw8cbrr891NwbK0smTJ+d8fHOU9nHy5Mm57saB9cbrr8/534ejtI+RkZFZ6auEW8CHSCQiK1ShznCYg8P3YZ/gAcy8znBYaxoa5nycc5TmYfcduLM/v+b678RRmocVqlAkEpmVvkq4BXywwy1QiM5wmHALFAnjCybs4AZ3tA9MEG6BgCLcwgTFN1A8jC+YILx5o31ggnALBBThFiYovoHiYXzBBOHNG+0DE4RbIKAItzBB8Q0UD+MLJghv3mgfmCDcAgFFuIUJim+geBhfMEF480b7wAThFggowi1MUHwDxcP4ggnCmzfaByYIt0BAEW5hguIbKB7GF0wQ3rzRPjBBuAUCinALExTfQPEwvmCC8OaN9oEJwi0QUIRbmKD4BoqH8QUThDdvtA9MEG6BgCLcwgTFN1A8jC+YILx5o31ggnALBBThFiYovoHiYXzBBOHNG+0DE4RbIKAItzBB8Q0UD+MLJghv3mgfmCDcAgFFuIUJim+geBhfMEF480b7wAThFggowi1MUHwDxcP4ggnCmzfaByYIt0BAEW5hguIbKB7GF0wQ3rzRPjBBuAUCinALExTfQPEwvmCC8OaN9oEJwi0QUIRbmKD4BoqH8QUThDdvtA9MEG6BgCLcwgTFN1A8jC+YILx5o31ggnALBBThFiYovoHiYXzBBOHNG+0DE4RbIKAItzBB8Q0UD+MLJghv3mgfmCDcAgFFuIUJim+geBhfMEF480b7wAThFggowi1MUHwDxcP4ggnCmzfaByYIt0BAEW5hguIbKB7GF0wQ3rzRPjBBuAUCinALExTfQPEwvmCC8OaN9oEJwi0QUIRbmKD4BoqH8QUThDdvtA9MEG6BgCLcwgTFN1A8jC+YILx5o31ggnALBBThFiYovoHiYXzBBOHNG+0DE4RbIKAItzBB8Q0UD+MLJghv3mgfmCDcAgFFuIUJim+geBhfMEF480b7wAThFggowi1MUHwDxcP4ggnCmzfaByYIt0BAEW5hguIbKB7GF0wQ3rzRPjBBuAUCinALExTfQPEwvmCC8OaN9oEJwi0QUIRbmKD4BoqH8QUThDdvtA9MEG6BgCLcwgTFN1A8jC+YILx5o31ggnALBBThFiYovoHiYXzBBOHNG+0DE4RbIKAItzBB8Q0UD+MLJghv3mgfmCDcAgFFuIUJim+geBhfMEF480b7wAThFggowi1MUHwDxcP4ggnCmzfaBybKN9xOjivS26venMdHGvz4kmLxWX1VQN4It+Xshi4PHlfnsUFdznUOisc0fr5X3Ud+rqPvDWg4OunrN1B8A8XD+ColccUiv9CB/QfVO3Ej80uTVzQ8cFJHf9ql7t7faTx2M/NfTvTqJ/tb1RWJzugrIrx5K5X2iccu6ePBj5K54kOd6v4/amncoqc2/1C9VwkYc6VMw21cX/S1aGWoQpbnYal2dZN+3DMqf2UjUHyE2zIW61frowtkrWpT5Gb2l+PRs+psekhV6eermk064ONcRfENFA/jq4RMDqnz6eW6q+m4JlJ5I67J0V/rlSeWZNSFVfft1OHBy5r6tk/V3bRSdZsOaej6zIWVUglvcyXw7TN5SQPhb6thoeWaL6rWHdInZNs5U6bh9gt9cmhzojCsWauml/dp/77042XtadyiR+6en+iIlQ/r2yf+JPohgoRwW6bin6mvZW3i/OQWbuPj6tmzWlWhatVvf1Wdx3+lrh806pGFlqyabTo8dC2vX0PxDRQP46tU3NBE9wu6q3KNWvqupP5r/PMP9MqD1bJC83XPxpd06Phv1H1wt9bVWLJqnjDYLf4AABjtSURBVFbHOftObVxfDPxAD1Wu0HPdn85YnRj48DbHAt0+8Qn17m9Iu/hcq/q1G/TUhif11IaNeuaF13Vq7K9z/SpvaWUabj/Tqd33T3v1JB77vX767L2J71v1Aw18QbxFcBBuy1D8sgbat6rO/lDMCrdxXT/XrjWVFap69IcaSK2bmNTFE3v0QKXluPuQG8U3UDyMrxIRH9LhdXeqqqFdkdSd16uKtK1XVcjSXc8e0eik/d/jip17U5tq5qnumbc1Gnf8jBm8Gxfo8BYAwW0f+zPaUt2GFnUPXmR5YwCVZ7i9eVbtq+bLCs3TyuYz+iLnN6ZNX67crMOf5P5OYLYRbstLPPo7Hd33VdWFKlT15WVaVukWbu2iy+UuwfVBtTcskLXoBXU71425oPgGiofxVQrsIFKnzeELU+fTL86oZcU8WZXr1X7uquPfJG+OZHxtUhePbNftlY+pdeAvM/LKghvegiG47ZP8jHbtOwiKsgy38YtHtO22Clmhxdp25I+e00huRtr0EOEWAZR/uP2rxiNn1Nt7XuOTNxQb/UhH32zVK61v6u33Iro8mWsE3FRsbFDvH/2ZDre16JXWDnUe/UBDn113//bJCUXe69Lhth+q/a2jOjU04Vj/eUPR4YHkxgpnFBl3m5Zjv9be5OvNfG3x2Kj63/25Olqb1drxc73bP+pyVbTQ9zuXxtXduCyxzv/Rl9R9tktNd7iE2+QdAuu27eq66FxdG1V/82pZofu1p+ezaX8jxTdQPIWPr/RzYK4j+9woSfHYH3X62Ftqb/6Ox/nRz++Y1OWhPo/ztX1O/0gDg/+h072n1T8cddRUcU2On3d8zf79AxqOOi/E2V+zf2c+r9X5vW4/103ynOmo71I14ooW9WfN2EsG2dCdWn9oKPVe458c0vrK6W6Y5C+44S0YAts+8T+q6+nFU30nHtP4+X719vYrMhZ11ET5ji/76+Y1FBLKMNzGdbVnr5aEKmRVblDHkNe89+saDW/T7UxLxgzoDId17NgxjYyMzMjPyz/cJoPTHTsVfr9Nm2rSNziwVLfxdQ04C4H4ZQ0e2qn6SpeN1mq26scDlzMKmHi0Xz/euDTz+yof1reOj6SdzGOKtK1Nfn2B1rQNKism23cfQxWy7nhe3VfsZHdD0aEj2lVf7Xg9dWrYczxt2liB73fOjau7aY02ffeYhqI3pCvd7uH2ao/2LLZ8FV25EG6BhJGREb164FWdPHlSly5dmpGfWfj4si90eWx2mXFulKQbig68qW3L5+dxfvTzO75InlMsLdndo6z7UHYhf9vX9frr39SXQvP1UNtZZW4TcFNXup93fM3+/WvVHoll/sjRt/X1GktWaJmausfze61Z35v9c13Zd2gd59PUTQ3XDf3s9+NoE3tGoOu52b/AhrcCnDx5Um+8/rrOnDmja9fy2xNiOoFtn2Q/+FLjcV0aPa69j9ZljsddP1MkVX9M5jm+7IvZJjUU0pVhuE3bTGrxXp3KuRX3dU30tScKYzaUwgzYumVr6iRXV1urpsZGo7DrO9xWLtbyL1cn14Fc0OjQBzrc9FBiXdGOd3Qx1cFvaKLnZT1QWaGq+3ao7WiP+s9FNNj7rg4ld+jNvNjzFw20PqaqULUeaPqJ3vvPAfUdbdZTNZasmh3qGrVPv/aJuVq1C+e5rk+6OdShr1RmF3Dxi+/q2/XVsipX6pnv/0KnBgY1cOoXav3aSlWFqrVq/wf6PPWz/L7fIPhCl8evTF0IyBVuc/13Se5FZG6EWyDBPpfax30rV+rll14yCrvm4bZWj+9+Q53hcNrxPT27fJ6jaI3r+tAhba6xZFU+qGfb/q9O9fXpzIm3tPeJJbJC1Xpgz/uOdfj27/h7Pdv6VubvOLhbj982df71uotpf61q3U/0H7/Kde7xE26vqK95TXIjHjuwxjTc05V6feHW7bonVCFr+Xa1pl53l04Nxzx+rrvE5012sEjchZ3uPFuhLzV2a2oLKnu68nQ3TfIT2PBWgM5wOGN8fWXNGr322mtGYTew7XOlW013zNcD//tlvVBfLWvho9rR/IbCh36k3RtWqCpkqW7jm4okp1TkN77sWqnwGgqZyjDcpl0FzDg52keHWve/qMa1yxMn2IWPaU/XeUUDVQijFKWHW/u4/bZ5BYdd3+E2VJG9HtO+ype+PiQ+qqPPLpfltq4ztRYpbRqXfTcx42fbU2TT7yLaJ+aVenztvS5Ta5MXnioXqPZvrbQTs13wLFBDa7/SS5Z49LQOPOp4/X7fb9HEdf3cv+urmwq4U5wjxOZ3R8FZdLkj3AIJznDrPAoJu+bh1g53aey7g+lFa/xTdTetcL2Tk9rxN+t85xEC7XOP/Tvsu0dZPyO5y3DoTq0/9DtdznlhLf9wO3XXtsL9/Wu6c6CfcGu/LpeZLq6faTb7s815nrVvnEy/3C0fgQ1vBXCGW+dRSNgNbPtc6VbTHZbuXLhAVTXP6Cfn0qbpT15Q17P3ygot09ePDCf+e17jy7SGglP5hVu7OPec4pI8Fjbo+SO/z77tDxTALdyahF3/4dZtGos9LWaBvtJxPlF4XB/Wqbfa1Lz3LfVfyzWdLa14mIxqLHJG7/f9Me1n2yfh9ILG/m9f0Xdan9OS0Ertei+tUEye5KtWb9Y/3ZdWwNlj1rXQsJcOpH8A+Hy/xWQ/A9HvVOhpwm2uXTntrxNugfxNF24LCbuzFm4/P6Fdi6wcM9Hs86NzLaiPcJsKbc5z5iW998LKZFEeTQZFtzWn+Ybb5EXMyof1zNb6WQi39ueRy+9Ju2CQdUF14rieW5QM4Bmvwd/MmekENrwVYLpwW0jYDWz72OMnVK1VzaeV+erTnnaQ2p07n/Flh94CayhkKbtwm5puElqqp/a96bhrG1Zn+KDam1/Srq+tUm2oQlZoida1fJDXozUAL/mEWz9h13+4Xa2WvmjWV/MPRJOKjn2o9g110xcPqXUf6Zsb2SfmtWr/8B3tWjQvYzpYYgrOAq350UF9P62As8ese6Cb2tF86vXP1PudGYkp1QsSG0WN5jldraA7t25tkRvhFkjwG27zCbuzFW7tc8LtTx9xXWrhfkHMT7iV+zk4eXfTLtJzv478wm3iru083dX0tn6bK3Qq33C7Ri09FzQ2NqaxsT8r6rqpjtfnRFyxgR+qobJiailMaqr3UtXevVS1Lu91Jj9bAhveCuA33OYTdgPbPqlw615/pMZw2l3XfMZXQmE1FLKVWbhN30xqut2Pr2ui5xWtqqyQ6/RMwKdCwq1X2F2/bp2sUEUe05jtNajufT7n+qLJCQ31HNVbbc3a0/i0Hr+vNu21uIfb+PARPb9hQ/J7l2pTe3/alP60E/O532fuKJiagrNaLR99kFbA3Zh6HNc0x9QHQ4HvN+ObYrr8p7FkcWR6fKzetuSza2u+qv3vnJ1+x+ZZmpa8pqHB5QIfB8etdbx64IDxuTn9WFz3d1q29G6tX7eugDW7fsJtHmPe9VziL9zq5nl1/MOCtILcvpCWdqfWnspb87Q6zqUX9X/VaPh/6nbPcGvftV2v9nOXct9RVb7h1vk3ma/laxt1oOts2ufRdHd5/6rR4y/qAcemilX1L+qXx1tcQyzh1l1n2CzcuoXd5Xcv06sHXp2xDapmjD1+XJ9oILn2u3zGl6TCaijCrZsyC7dTayXy2tEubQrzbN3lQaaZPCGW6/HG669PE3Dt3YNznOiyip+4Jkd/rVeeWJL2eyzV3veknmv+nnavrc1ZEKQKj+S/yZyOm3ZijlxJrg2xN99IbsaxokX9sfQCbjJVvFXdvVpPbnhST+U6njui4fRwm/f7dZG6+lqMY75W7vsge2fEfF7jDG8odc/y5WrcuZOD45Y+/mmr+YVHt+PvFi1SZzjsswAvJNx6PIJmJsJt6vna9npSu5ZKvzsV1UDrE8m9Sh7Vs7tf1v6Xd+mfH12W3CAqd7idumt7XBNxj+nCyjfcLtHjjXu1f98+7d/dqGf+cbWWJ2fsbeoYTE4zzmcK83VdjryrjuY92vXCv6n10Hv6Q/RG8jVkb0Q13V10P+a6riiFY+uWLTp27JhZQ8801/GTzq3f5TO+pMJqKMKtGytUTuHWXrid78nH/iAJEW5hbibu3KZPzzlz5oyskJ9pyd6BNHXn8/p5Hd60VFaoWvXbf6SjvRENj9vPZ8tzTdPkuHqb16oqY91r+ok5llx7klwre7VHexYnp9hkFHA3fE21Lej9ugnondvU3RHX9XX+NjTpDDMtGZBkPC15qtjeqs5wWJFIxGB8+Qm3U7PRcp0fU7uxGoVb+06SpbteOKHP7WUnzvPQ5Kh6WrfpnvS7nQsf1JNrV6oqZ7j9NO2u7VV5roVVoWtubyp24WfasciSVdOooxcnvdvAU+6NqLhz687kzu28ykpZoeylWYFtH5dpxxlSOSS93+U5vgqqoQi3bsor3NqFYZ7PgZzauW/mHsyNW1ch4dZrY4WZWXNrF0dTV6FT03bvfUW9zg2lXE/MkiavKhrLPInm3sY++W+TMyNuf/ptjfS1aKW9PtdxYp5uGnH8L+MaGftMsazpZvm932KLX3xH31w0T3VPfEcnDNfcKj6kw+vuzDHlOnnlNtdaHwfCLZBQaLhND7NOsxNuc6zXS8m1Dt9vuNXUTLbFe/Xbswe13uUROvbvnIxe1B8Gz+oPo39WdPKG55rb144fTLtrKxUn3EpT50d7Hwjn/09/C1EN959W76lB/SnrQmSu8+zMfrYENrwVwE+4zRVmnQLbPqkaKcfnsD2OChpfhdVQyFZW4XZqMymXk5nT5Ii6dz2cmE4zK48NQbnLJ9z62RJ/ZnZLvqLefQ/JSt3t874TMLVTpF08TOpi94t6YGFt9gWjrIDmODHbRcKi7Wp+aa2q7N2QnSdmz8f3uO0G6uf9FtkM75Y8NX2pTpvDFzJf/7UPtf/eedM8v3sK4RZIyDfceoVZp9kKt6mi+LZt6hx1PtvBfoya84J+AeE2NVXyQf1L41d1u3On1py8NpRaovr76nLsCDvT4db+ml3/ee2WbD+eJfsiYuozMOs8y27JuXiF23zDrFNw22dq9+Ps+iOua72vaEXIbfZoPuOrwBoKWcoo3NqPAKlwny4wGdX42JjGRofU331Q+zauSK4TSV+jARTOLdyaPMy8oOfc1mzT4SH799xQdOB1barJfJ7f1J3bl3Tq87RANnlRPfsakuNi6qpk6s5B/cvqST2qx97cIP0k7jwx22My8UDy1PdlnZjtQOdcwxvX5Ogv9a36almVa9TSZ0dxf++3eOK61ndADzV8T30z9JzbjEcJZLT3NQ0d2qa60Dyt2Peh8ulJhFsgIVe49RNmnWYt3KadH+969ohGU3ca0853NTvUlR58vaZO5gy39oXPeapdWO3jHOoVbitkhay0u7ZSUcJtPKaLvW3JtrCnJdvvxy2M2gGlWqv2f6DP7dcW/0x9Lc7lNs7XncfNkzwEN7z5lx5uCw2zTkFun9QFkJqt+vHA5dRFpXi0Xz/euFTum9TmM74KraHgVEbhNm0zqXyPypXa1vEfabvrAYX75298wyjMOvkPt3dq+d13ylr4qHY0/7s6mnfokYWWrMqH9e0Tf5o60abW3Fqqe+JFdYTD6jz0I+3esEJVNev07NaVmYVHfFw9e1arKlShqvu+ruaOt3S4tTH5s1drb8+44wHkaY9/sNeDpd9JdTsxxwbVsTHxmmpXb9f+toM63Pavemr5fFmhaj2w5/204sjn+w0ir42j4pc10J5Yw1u1fKN2v9am1heeTKxzW9SULNymR7gFEuxzqUmYdZq9cCuX8+Prat+3PXG+Cy3V5kPnE0EsfkFdz61T/cLkc1rdZnl4bYiTWtrlZ9OkacJtxgVIaWbCba3q125Ibja4Xo/cPT9Z16W1haY+f9zeS3zife2tr5YVqtMjz35HHQeTn4FZF1ntf5D7bm8hghze/OoMh43DrFOw2+evGj2yU3eFKpL1xxsKH/qemlbXJeqqp8P6xG3fjWnHl0ENhQzlE27ttWrThtr5Wr56i55rCevUJ9FgF8C4pfkPt4+ptfuXav3ayuTd1wpVLd+ilhMjyoxDcU2Oncz4Pis0X/ds/K6ODl1JXV1Mv0MYj55X1+7Hks+GTh4LH9Pe7vSfnX1idl1DmuPEHI+eVde+zY7NShrU1N6jsYwPCr/vN4Cm29F58s/qe+MbaW1hqfbRb+un567kfc4i3ALFM6vhVonz4093fSXjHFy1fIuaj/5u6gJ92iaZVcu36ECPyyMOPXd7vaT3Xljpc1mHV7it1qrm046ZJjMRbp11Xa3qN3xL7e/+PvNmhf3547qUI67J0d+oJTWLr0JWqE4Nu36miNtMHPu5pF4bFfoQ7PA29wLfPvHPNdS1Rw32haTp+o+k6ceXWQ2FKeUTboEy4z/cJk+I8ZjGz/fr9OAFTcQ8TnzxmCY+HtTp3n5FxqJ5BMKbik1c0GBv7/Q/u2A3FftsRJG+0zo9+LEuRvN4jly+77fkxDUZHVOk77T6I2OKTrcDswPhFiieuRlf9jn4tPojI7o80+e7+Kfqblrh8QzPUmPv2eCxCV/qc3BQH0/EcgR6e+Ou/DYrzUfgw9scK5X2iccu6ePBj9Tr2X/sby638RVchFsgoAoOt2XvVnu/hSHcAsVTluPr8xPatWjm7k4GQfziO9pRM9/wiRjJZW/Otc0GSiW8zZWybJ8yHF9BRbgFAopwm8ut9n4LU5bFNxAQ5Te+YvokvF11bju1l7TkjrNuj77L17UPtf/e+Y6NscyUZXibQeXXPuU6voKJcAsEFOE2l1vt/Ram/IpvIDjKZnzdjOjw15/UU2vvT6znnZWd5meTvQO92w62+Ug+GWCGHxlZfuFtZpVN+5T9+Aomwi0QUITbXG6191uYsim+gQAqm/Fl7wIcqpBV+bC+dbwENuTzKz6h3v0Nur2hXZHrPuPt9UG1Nyx27NhvrmzCW5GUTfvcCuMrgAi3QEDlH25vKvbZpxob+7PvTYdK0632fgtTNsU3EEDlM75uKjZ2Vqd7P9J/jV0t2+mS8eiw+nsHNOz3meSxMQ0W8u+mUTbhrUjKp31ujfEVNIRbIKDyD7dAtvIpvoHgYXzBRPmEt+KgfWCCcAsEFOEWJii+geJhfMEE4c0b7QMThFsgoAi3MEHxDRQP4wsmCG/eaB+YINwCAUW4hQmKb6B4GF8wQXjzRvvABOEWCCjCLUxQfAPFw/iCCcKbN9oHJgi3QEARbmGC4hsoHsYXTBDevNE+MEG4BQKKcAsTFN9A8TC+YILw5o32gQnCLRBQhFuYoPgGiofxBROEN2+0D0wQboGAItzCBMU3UDyML5ggvHmjfWCCcAsEFOEWJii+geJhfMEE4c0b7QMThFsgoAi3MEHxDRQP4wsmCG/eaB+YINwCAUW4hQmKb6B4GF8wQXjzRvvABOEWCCjCLUxQfAPFw/iCCcKbN9oHJgi3QEARbmGC4hsoHsYXTBDevNE+MEG4BQKKcAsTFN9A8TC+YILw5o32gQnCLRBQhFuYoPgGiofxBROEN2+0D0wQboGAItzCBMU3UDyML5ggvHmjfWCCcAsEFOEWJii+geJhfMEE4c0b7QMThFsgoAi3MEHxDRQP4wsmCG/eaB+YINwCAUW4hQmKb6B4GF8wQXjzRvvABOEWCCjCLUxQfAPFw/iCCcKbN9oHJgi3QEARbmGC4hsoHsYXTBDevNE+MEG4BQKKcAsTFN9A8TC+YILw5o32gQnCLRBQhFuYoPgGiofxBROEN2+0D0wQboGAItzCBMU3UDyML5ggvHmjfWCCcAsEFOEWJii+geJhfMEE4c0b7QMThFsgoAi3MEHxDRQP4wsmCG/eaB+YINwCAUW4hQmKb6B4GF8wQXjzRvvABOEWCCjCLUxQfAPFw/iCCcKbN9oHJgi3QEARbmGC4hsoHsYXTBDevNE+MEG4BQKKcAsTFN9A8TC+YILw5o32gQnCLRBQhFuYoPgGiofxBROEN2+0D0wQboGAItzCBMU3UDyML5ggvHmjfWCCcAsEFOEWJii+geJhfMEE4c0b7QMThFsgoAi3MEHxDRQP4wsmCG/eaB+YINwCAUW4hQmKb6B4GF8wQXjzRvvABOEWCCjCLUxQfAPFw/iCCcKbN9oHJgi3QEARbmGC4hsoHsYXTBDevNE+MEG4BQLKDrccHIUeFN9AcXSGw3M+vjlK+yC85da4c+ec/304Svsg3AIBdO3aNUUiEQ6Ogo+RkZG57sZAWbp06dKcj2+O0j4uXbo01904sEZGRub878NR2se1a9dmpa8SbgEAAAAAJY9wCwAAAAAoeYRbAAAAAEDJI9wCAAAAAEoe4RYAAAAAUPIItwAAAACAkke4BQAAAACUPMItAAAAAKDkEW4BAAAAACWPcAsAAAAAKHmEWwAAAABAySPcAgAAAABKHuEWAAAAAFDyCLcAAAAAgJJHuAUAAAAAlDzCLQAAAACg5BFuAQAAAAAl7/8DkjNFwWi3shcAAAAASUVORK5CYII=;" parent="1" vertex="1">
<mxGeometry x="890" y="300" width="310.11" height="90" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-111" value="<div align="left">Доставка последнего элемента из коллекции или итеративный обход выдают исключение, что <br></div><div align="left">нежелательно</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="410" width="550" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-112" value="<div>В течение всего времени итеративного обхода владея замком на Vector, мы не позволяем другим потокам <br></div><div>изменять его (см. листинг 5.4). К сожалению, от этого страдает конкурентность.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="445" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-113" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="490" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-114" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="QMmgmNxQZZJa730i63d_-113" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-115" value="<font style="font-size: 14px">5.1.2 Итераторы и исключение ConcurrentModificationException<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-113" vertex="1">
<mxGeometry x="10" y="5" width="430" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-116" value="<div>Класс Vector как и другие современные коллекции содержат проблемы составных действий. <br></div><div><br></div><div>Обычно обход коллекции выполняется с помощью <b>Iterator </b>в сочетании с замком. Итераторы не <br></div><div>проектировались для конкурентного выполнения изменений, по этому в случае обнаружения изменений <br></div><div>коллекции во время обхода, итератор выдает <i>ConcurrentModificationException</i>, то есть быстро <br></div><div>отказывают (<b>fail-fast</b>). <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="545" width="620" height="90" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-117" value="<div align="left">Во время обхода коллекции нужно держать замок, если коллекция большая, это непроизводительно.</div><div align="left">Это может также вызвать взаимную блокировку.</div><div align="left">Альтернативой является клонирование коллекции для обхода, но замок все равно будет на коллекции. <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="640" width="610" height="50" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-118" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="710" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-119" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="QMmgmNxQZZJa730i63d_-118" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-120" value="<font style="font-size: 14px">5.1.3 Скрытые итераторы<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="QMmgmNxQZZJa730i63d_-118" vertex="1">
<mxGeometry x="10" y="5" width="190" height="20" as="geometry" />
</mxCell>
<mxCell id="QMmgmNxQZZJa730i63d_-121" value="<div align="left">Методы <b>containsall</b>, <b>removeAll </b>и <b>retainAll </b>выполняют скрытый обход коллекций. Они также вызывают <br></div><div align="left"><b>ConcurrentModificationException </b>по<b> </b>этому <br> </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="755" width="580" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-1" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="800" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-2" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="8ZVaQMv6SIjStNIvOHQu-1" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-3" value="<b><font style="font-size: 14px">5.2. Конкурентные коллекции <br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="8ZVaQMv6SIjStNIvOHQu-1" vertex="1">
<mxGeometry x="10" y="5" width="230" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-4" value="<div align="left">Версия <b>Java 5.0</b>. предлагает хеш-массив <b>ConcurrentHashMap </b>вместо синхронизированных хешированных <br></div><div align="left">реализаций <b>Map</b>, и <b>CopyOnWriteArrayList </b>вместо синхронизированных реализаций <b>List </b>для <br></div><div align="left">случаев, где обход является доминирующей операцией.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="850" width="620" height="50" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-5" value="<div align="left">Интерфейс <b>ConcurrentMap </b>поддерживает составные действия "добавить если отсутствует", замена и условное <br></div><div align="left">даление.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="910" width="650" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-6" value="<div align="left"><b>Замена синхронизированных коллекций конкурентными коллекциями может предложить значительные <br></b></div><div align="left"><b>улучшения масштабируемости при небольшом риске.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="960" width="630" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-8" value="Queue" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1060" y="1010" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-9" value="BlockingQueue" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1390" y="1100" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-10" value="<div>ConcurrentLinkedQueue</div><div>FIFO<br></div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1100" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-11" value="<div>PriorityQueue</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1050" y="1100" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-12" value="LinkedList" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1210" y="1100" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-13" value="" style="endArrow=classic;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="8ZVaQMv6SIjStNIvOHQu-8" target="8ZVaQMv6SIjStNIvOHQu-10" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1010" y="1080" as="sourcePoint" />
<mxPoint x="1060" y="1030" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-14" value="" style="endArrow=classic;html=1;exitX=0.47;exitY=1.053;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitPerimeter=0;" parent="1" source="8ZVaQMv6SIjStNIvOHQu-8" target="8ZVaQMv6SIjStNIvOHQu-11" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1102.5" y="1050" as="sourcePoint" />
<mxPoint x="975" y="1110" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-15" value="" style="endArrow=classic;html=1;exitX=0.597;exitY=1.03;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="8ZVaQMv6SIjStNIvOHQu-8" target="8ZVaQMv6SIjStNIvOHQu-12" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1131.1" y="1051.59" as="sourcePoint" />
<mxPoint x="1135" y="1110" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-16" value="" style="endArrow=classic;html=1;exitX=0.868;exitY=1.03;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.366;entryY=0.007;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="8ZVaQMv6SIjStNIvOHQu-8" target="8ZVaQMv6SIjStNIvOHQu-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1147.6100000000001" y="1050.8999999999999" as="sourcePoint" />
<mxPoint x="1265.163967611336" y="1110" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-17" value="<div align="left"><b>BlockingQueue </b>добавляет блокирующие операции вставки и извлечения. Блокирующие очереди полезны <br></div><div align="left">в паттернах проектирования "<b>Производитель-потребитель</b>". <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1150" width="600" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-18" value="<div><b>Java 6</b>. <b>ConcurrentSkipListMap </b>и <b>ConcurrentSkipListSet </b>конкурентные версии <b>SortedMap </b>и <b>SortedSet</b> (<i>TreeMap </i>и</div><div><i>Treeset</i>, обернутых в <i>synchronizedMap</i>)<br> </div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1200" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-20" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="1250" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-21" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="8ZVaQMv6SIjStNIvOHQu-20" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-22" value="<font style="font-size: 14px">5.2.1 ConcurrentHashMap<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="8ZVaQMv6SIjStNIvOHQu-20" vertex="1">
<mxGeometry x="10" y="5" width="180" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-23" value="Класс <b>ConcurrentHashMap </b>— это хешированный ассоциативный массив <b>Map</b>, аналогичный хеш-массиву <b>HashMap</b>, но <b>использующий другую замковую стратегию</b>." style="text;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1295" width="550" height="40" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-24" value="<div align="left">Вместо <b>синхронизации каждого метода</b> на общем замке и ограничения доступа одним потоком за раз он <br></div><div align="left">использует <b>замковое расщепление</b> на полосы (<b>lock striping</b>)</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1340" width="620" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-25" value="<div align="left"><b>ConcurrentHashMap </b>предоставляет итераторы, которые не выдают исключение <b>ConcurrentModificationException</b>, <br></div><div align="left">являются не быстро отказывающими, а <b>слабо непротиворечивыми </b>(<b>weakly consistent</b>).</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1385" width="670" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-26" value="<div>Однако семантика методов, работающих на всем ассоциативном массиве <b>Map</b>, таких как <b>size </b>и <b>isEmpty</b>, <br></div><div>была <b>немного ослаблена</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1430" width="610" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-27" value="<div>В большинстве случаев замена синхронизированных реализаций ассоциативного массива <b>Map </b>на хеш-массив <br></div><div><b>ConcurrentHashMap </b>приводит к <b>более высокой масштабируемости</b>. Но если вам необходимо только <b>защитить <br></b></div><div><b>ассоциативный массив замком для эксклюзивного доступа</b>, то <b>ConcurrentHashMap </b>вам не подойдет.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1470" width="650" height="50" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-28" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="1540" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-29" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="8ZVaQMv6SIjStNIvOHQu-28" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-30" value="<font style="font-size: 14px">5.2.2 Дополнительные атомарные операции над ассоциативным массивом<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="8ZVaQMv6SIjStNIvOHQu-28" vertex="1">
<mxGeometry x="10" y="5" width="520" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-31" value="<div align="left">Операции «<b>добавить, если отсутствует</b>», «<b>удалить, если равно</b>» и «<b>заменить, если равно</b>» сразу задаются <br></div><div align="left">интерфейсом <b>ConcurrentMap </b>как <b>атомарные</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1585" width="640" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-32" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="1630" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-33" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#ffe6cc;strokeColor=#FF8000;" parent="8ZVaQMv6SIjStNIvOHQu-32" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-34" value="<font style="font-size: 14px">5.2.3 CopyOnWriteArrayList<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="8ZVaQMv6SIjStNIvOHQu-32" vertex="1">
<mxGeometry x="10" y="5" width="190" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-35" value="<div>Класс <b>CopyOnWriteArrayList </b>является конкурентной версией синхронизированного спискового класса <b>List</b>, <br></div><div>который предлагает более высокую конкурентность и устраняет необходимость в блокировке или <br></div><div>клонировании коллекции во время итеративного обхода.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1676" width="630" height="50" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-36" value="<div><b>Итераторы </b>не выдают исключения <b>ConcurrentModificationException </b>и возвращают элементы, не измененные</div><div> с момента создания итератора.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1739" width="640" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-37" value="<div><b>Копирование массива обходится дорого</b>, его целесообразно использовать только когда <b>итеративный обход <br></b></div><div><b>встречается гораздо чаще, чем изменение</b>. <br></div><div>Например, доставка уведомления требует <b>итеративного обхода списка</b> зарегистрированных слушателей и <br></div><div>вызова каждого из них, а регистрация или дерегистрация слушателей происходят гораздо реже.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="890" y="1780" width="650" height="60" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-38" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="880" y="1860" width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-39" value="" style="rounded=0;whiteSpace=wrap;html=1;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="8ZVaQMv6SIjStNIvOHQu-38" vertex="1">
<mxGeometry width="660" height="30" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-40" value="<b><font style="font-size: 14px">5.3. Блокирующие очереди и паттерн «производитель-потребитель» <br></font></b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="8ZVaQMv6SIjStNIvOHQu-38" vertex="1">
<mxGeometry x="10" y="5" width="510" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-42" value="<font style="font-size: 72px" color="#CC0000"><b>REST</b></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=85;" parent="1" vertex="1">
<mxGeometry x="-1965" y="-1570" width="210" height="40" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-43" value="<p><font style="font-size: 11px" color="#CC0000">RE</font><font size="3">presentational <font color="#CC0000">S</font>tate <font color="#CC0000">T</font>ransfer</font></p>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-1980" y="-1525" width="240" height="50" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-44" value="Это <b>архитектура</b>, т.е. <b>принципы построения распределенных гипермедиа систем</b>,<br>того что другими словами называется <b>World Wide Web</b>, включая универсальные<br><b>способы обработки и передачи состояний ресурсов по HTTP</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="-1200" width="500" height="50" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-45" value="<i>Автор идеи и термина Рой Филдинг 2000г.</i>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-1990" y="-1140" width="260" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-47" value="SOAP" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-1387" y="-1520" width="50" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-48" value="WSDL" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-1100" y="-1520" width="50" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-49" value="<div align="left"><b>Что нам дает REST подход:</b></div><div align="left"><b></b><br>- <b>Масштабируемость </b>взаимодействия компонентов системы (приложения)<br>- <b>Общность </b>интерфейсов<br>- Независимое <b>внедрение компонентов</b><br>- <b>Промежуточные компоненты</b>, <b>снижающие задержку</b>, усиливающие <b>безопасность</b><br><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="-1095" width="490" height="100" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-50" value="<div align="left"><b>Когда использовать REST?</b></div><div align="left"><br></div><div align="left">- Когда есть <b>ограничение пропускной способности соединения</b><br>- Если необходимо <b>кэшировать запросы</b><br>- Если система предполагает значительное <b>масштабирование</b><br>- В сервисах, использующих <b>AJAX</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="-990" width="390" height="90" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-51" value="<div align="left"><b>Преимущества REST:</b></div><div align="left"><br>- <b>Отсутствие дополнительных внутренних прослоек</b>, что означает передачу данных <br></div><div align="left">в том же виде, что и сами данные. Т.е. данные не оборачиваются в XML, как это делает <br></div><div align="left">SOAP и XML-RPC, не используется AMF, как это делает Flash и т.д. <b>Просто отдаются сами данные.</b><br></div><div align="left"><br></div><div align="left">- Каждая единица информации (<b>ресурс</b>) однозначно определяется URL — это значит, <br></div><div align="left">что <b>URL по сути является первичным ключом для единицы данных</b>. Причем совершенно <br></div><div align="left">не имеет значения, в каком формате находятся данные по адресу — это может быть и HTML, <br></div><div align="left">и jpeg, и документ Microsoft Word.<br></div><div align="left"><br></div><div align="left">- Как происходит <b>управление информацией ресурса — это целиком и полностью основывается <br></b></div><div align="left"><b>на протоколе передачи данных</b>. Наиболее распространенный протокол конечно же <b>HTTP</b>. <br></div><div align="left">Для HTTP действие над данными задается с помощью методов : <b>GET </b>(получить), <b>PUT </b>(добавить, заменить), <br></div><div align="left"><b>POST </b>(добавить, изменить, удалить), <b>DELETE </b>(удалить). Таким образом, действия <br></div><div align="left"><b>CRUD </b>(Create-Read-Update-Delete) могут выполняться как со всеми 4-мя методами, <br></div><div align="left">так и только с помощью GET и POST.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="-880" width="620" height="240" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-52" value="<div align="left"><b>Что такое RESTful:</b></div><div align="left"><br>Чтобы распределенная система считалась сконструированной по REST архитектуре (Restful), <br></div><div align="left">необходимо, чтобы она удовлетворяла следующим критериям:</div><div align="left"><br></div><div align="left">- <b>Client-Server.</b> Система должна быть разделена на клиентов и на серверов. Разделение <br></div><div align="left">интерфейсов означает, что, например, клиенты не связаны с хранением данных, которое остается внутри <br></div><div align="left">каждого сервера, так что мобильность кода клиента улучшается. Серверы не связаны с интерфейсом <br></div><div align="left">пользователя или состоянием, так что серверы могут быть проще и масштабируемы. <br></div><div align="left">Серверы и клиенты могут быть заменяемы и разрабатываться независимо, пока интерфейс не изменяется.<br></div><div align="left"><br></div><div align="left"><b>Stateless</b>. Сервер не должен хранить какой-либо информации о клиентах. В запросе должна храниться <br></div><div align="left">вся необходимая информация для обработки запроса и если необходимо, идентификации клиента.</div><div align="left"><br></div><div align="left"><b>Cache</b>․ Каждый ответ должен быть отмечен является ли он кэшируемым или нет, для предотвращения <br></div><div align="left">повторного использования клиентами устаревших или некорректных данных в ответ на дальнейшие запросы.<br><b><br></b></div><div align="left"><b>Uniform Interface</b>. Единый интерфейс определяет интерфейс между клиентами и серверами. Это упрощает <br></div><div align="left">и отделяет архитектуру, которая позволяет каждой части развиваться самостоятельно.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="-625" width="620" height="270" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-53" value="<div align="left"><b>Четыре принципа единого интерфейса:</b></div><div align="left"><br></div><div align="left"><b>Identification of resources</b> (<b>основан на ресурсах</b>). В REST <b>ресурсом </b>является все то, чему можно дать <b>имя</b>. <br></div><div align="left">Например,пользователь, изображение, предмет (майка, голодная собака, текущая погода) и т.д. Каждый <br></div><div align="left">ресурс в REST должен быть <b>идентифицирован </b>посредством стабильного <b>идентификатора</b>, который не <br></div><div align="left">меняется при изменении состояния ресурса. <b>Идентификатором в REST является URI</b>.</div><div align="left"><br></div><div align="left"><b>Manipulation of resources through representations</b>. <b>(Манипуляции над ресурсами через представления).</b> <br></div><div align="left">Представление в REST используется для выполнения действий над ресурсами. Представление ресурса <br></div><div align="left">представляет собой текущее или желаемое состояние ресурса. Например, если ресурсом является <br></div><div align="left">пользователь, то представлением может являться XML или HTML описание этого пользователя.</div><div align="left"><br></div><div align="left"><b>Self-descriptive messages (само-документируемые сообщения).</b> Под само-описательностью имеется ввиду, <br></div><div align="left">что запрос и ответ должны хранить в себе всю необходимую информацию для их обработки. Не должны быть <br></div><div align="left">дополнительные сообщения или кэши для обработки одного запроса. Другими словами отсутствие состояния, <br></div><div align="left">сохраняемого между запросами к ресурсам. Это очень важно для масштабирования системы.</div><div align="left"><br></div><div align="left"><b>HATEOAS (hypermedia as the engine of application state)</b>. Статус ресурса передается через содержимое body, <br></div><div align="left">параметры строки запроса, заголовки запросов и запрашиваемый URI (имя ресурса). Это называется гипермедиа <br></div><div align="left">(или гиперссылки с гипертекстом). HATEOAS также означает, что, в случае необходимости ссылки могут <br></div><div align="left">содержатся в теле ответа (или заголовках) для поддержки URI , извлечения самого объекта или запрошенных <br></div><div align="left">объектов.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2040" y="-330" width="640" height="310" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-54" value="<div align="left"><b>Layered System.</b> В REST допускается разделить систему на иерархию слоев но с условием, что каждый компонент <br></div><div align="left">может видеть компоненты только непосредственно следующего слоя. Например, если вы вызывайте службу PayPal <br></div><div align="left">а он в свою очередь вызывает службу Visa, вы о вызове службы Visa ничего не должны знать.<br><b><br></b></div><div align="left"><b>Code-On-Demand (опционально).</b> В REST позволяется загрузка и выполнение кода или программы на стороне <br></div><div align="left">клиента.<br></div><div align="left"><br></div><div align="left"><b>Важно !</b> Сама архитектура REST не привязана к конкретным технологиям и протоколам, но в реалиях современного Веб, <br></div><div align="left">построение RESTful API почти всегда подразумевает использование HTTP и каких-либо распространенных форматов <br></div><div align="left">представления ресурсов, например JSON, или, менее популярного сегодня, XML.<br><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2068" y="-5" width="680" height="160" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-55" value="<b>Идемпотентность</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2072" y="152" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-56" value="<div align="left">С точки зрения RESTful-сервиса, операция (или вызов сервиса) идемпотентна тогда, когда клиенты могут делать один <br></div><div align="left">и тот же вызов неоднократно при одном и том же результате на сервере. Другими словами, <b>создание большого <br></b></div><div align="left"><b>количества идентичных запросов имеет такой же эффект, как и один запрос</b>. Заметьте, что в то время, как <br></div><div align="left">идемпотентные операции производят один и тот же результат на сервере, ответ сам по себе может не быть тем же <br></div><div align="left">самым (например, состояние ресурса может измениться между запросами).</div><div align="left"><br></div><div align="left">Методы <b>PUT </b>и <b>DELETE </b>по определению <b>идемпотентны</b>. Тем не менее, есть один нюанс с методом DELETE. <br></div><div align="left">Проблема в том, что успешный DELETE-запрос возвращает статус 200 (OK) или 204 (No Content), но для последующих <br></div><div align="left">запросов будет все время возвращать 404 (Not Found), Состояние на сервере после каждого вызова DELETE то же <br></div><div align="left">самое, но ответы разные.</div><div align="left"><br></div><div align="left">Методы <b>GET</b>, <b>HEAD</b>, <b>OPTIONS </b>и <b>TRACE </b>определены как <b>безопасные</b>. Это означает, что они предназначены только для <br></div><div align="left">получения информации и не должны изменять состояние сервера. Они не должны иметь побочных эффектов, за <br></div><div align="left">исключением безобидных эффектов, таких как: логирование, кеширование, показ баннерной рекламы или увеличение <br></div><div align="left">веб-счетчика.</div><div align="left"><br></div><div align="left">По определению, <b>безопасные операции идемпотентны</b>, так как они приводят к одному и тому же результату на <br></div><div align="left">сервере. Безопасные методы реализованы как операции только для чтения. Однако безопасность не означает, что <br></div><div align="left">сервер должен возвращать тот же самый результат каждый раз.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="190" width="690" height="270" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-57" value="<div align="left"><b>HTTP методы для создания RESTful сервисов</b></div><div align="left"><br></div><div align="left">HTTP метод <b>GET </b>используется для получения (или чтения) представления ресурса. В случае “удачного” (или не <br></div><div align="left">содержащего ошибок) адреса, GET возвращается представление ресурса в формате XML или JSON в сочетании с <br></div><div align="left">кодом состояния HTTP 200 (OK). <br></div><div align="left">В случае наличия ошибок обычно возвращается код 404 (NOT FOUND) или 400 (BAD REQUEST).</div><div align="left"><br></div><div align="left">GET http://www.example.com/api/v1.0/users (вернуть список пользователей)<br>GET http://www.example.com/api/v1.0/users/12345 (вернуть данные о пользователе с id 12345)<br>GET http://www.example.com/api/v1.0/users/12345/orders</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="470" width="650" height="150" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-58" value="<div align="left">HTTP метод <b>PUT </b>обычно используется для предоставления возможности обновления ресурса. Тело запроса при <br></div><div align="left">отправке PUT-запроса к существующему ресурсу URI должно содержать обновленные данные оригинального ресурса <br></div><div align="left">(полностью, или только обновляемую часть).</div><div align="left"><br></div><div align="left">Для создания новых экземпляров ресурса предпочтительнее использование <b>POST </b>запроса. В данном случае, при <br></div><div align="left">создании экземпляра будет предоставлен корректный идентификатор экземпляра ресурса в возвращенных данных <br></div><div align="left">об экземпляре.</div><div align="left"><br></div><div align="left">При успешном обновлении посредством выполнения <b>PUT </b>запроса возвращается код 200 (или 204 если не был передан</div><div align="left"> какой либо контент в теле ответа). <b>PUT не безопасная операция</b>, так как вследствии ее выполнения происходит .</div><div align="left">модификация (или создание) экземпляров ресурса на стороне сервера, но этот метод идемпотентен. Другими словами, <br></div><div align="left">создание или обновление ресурса посредством отправки <b>PUT </b>запроса — ресурс не исчезнет, будет располагаться там</div><div align="left">же, где и был при первом обращении, а также, многократное выполнение одного и того же <b>PUT </b>запроса не изменит <br></div><div align="left">общего состояния системы</div><div align="left"><br></div><div align="left">PUT http://www.example.com/api/v1.0/users/12345 (обновить данные пользователя с id 12345)<br>PUT http://www.example.com/api/v1.0/users/12345/orders/98765 (обновить данные заказа с id 98765 для пользователя <br></div><div align="left">с id 12345)</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2068" y="640" width="680" height="260" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-59" value="<br><div align="left">HTTP метод <b>POST </b>запрос наиболее часто используется для создания новых ресурсов. На практике он используется <br></div><div align="left">для создания вложенных ресурсов. Другими словами, при создании нового ресурса, POST запрос отправляется к <br></div><div align="left">родительскому ресурсу и, таким образом, сервис берет на себя ответственность на установление связи создаваемого <br></div><div align="left">ресурса с родительским ресурсом, назначение новому ресурсу ID и т.п.</div><div align="left"><br></div><div align="left">При успешном создании ресурса возвращается HTTP код 201, а также в заголовке `Location` передается адрес <br></div><div align="left">созданного ресурса.</div><div align="left"><br></div><div align="left">POST не является безопасным или идемпотентным запросом. Потому рекомендуется его использование для не <br></div><div align="left">идемпотентных запросов. В результате выполнения идентичных POST запросов предоставляются сильно похожие, <br></div><div align="left">но не идентичные данные.</div><div align="left"><br></div><div align="left">POST http://www.example.com/api/v1.0/customers (создать новый ресурс в разделе customers)<br>POST http://www.example.com/api/v1.0/customers/12345/orders (создать заказ для ресурса с id 12345)</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2068" y="895" width="670" height="220" as="geometry" />
</mxCell>
<mxCell id="8ZVaQMv6SIjStNIvOHQu-60" value="<div align="left">HTTP метод <b>DELETE </b>используется для удаления ресурса, идентифицированного конкретным URI (ID).<br>При успешном удалении возвращается 200 (OK) код HTTP, совместно с телом ответа, содержащим данные удаленного <br></div><div align="left">ресурса. Также возможно использование HTTP кода 204 (NO CONTENT) без тела ответа. Согласно спецификации <br></div><div align="left">HTTP, DELETE запрос идемпотентен. Если вы выполняете DELETE запрос к ресурсу, он удаляется. Повторный <br></div><div align="left">DELETE запрос к ресурсу закончится также: ресурс удален. Если DELETE запрос используется для декремента <br></div><div align="left">счетчика, DELETE запрос не является идемпотентным. Используйте POST для не идемпотентных операций.</div><div align="left"><br></div><div align="left">Тем не менее, существует предостережение об идемпотентности DELETE. Повторный DELETE запрос к ресурсу <br></div><div align="left">часто сопровождается 404 (NOT FOUND) кодом HTTP по причине того, что ресурс уже удален (например из базы <br></div><div align="left">данных) и более не доступен. Это делает DELETE операцию не идемпотентной, но это общепринятый компромисс <br></div><div align="left">на тот случай, если ресурс был удален из базы данных, а не помечен, как удаленный.</div><div align="left"><br></div><div align="left">DELETE http://www.example.com/api/v1.0/customers/12345 (удалить из customers ресурс с id 12345)<br>DELETE http://www.example.com/api/v1.0/customers/12345/orders/21 (удалить у ресурса с id 12345 заказ с id 21)</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2067" y="1140" width="670" height="200" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-1" value="<div><font color="#009900"><b><font style="font-size: 85px">Spring</font></b></font></div>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="260" y="-1640" width="280" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-2" value="<div align="left"><ul><li>singleton (creates the singleton bean. default value)<br></li><li>prototype (will return a different instance every time)</li></ul><ul><li><font color="#009900">request <font color="#000000">(creates a bean instance for a single HTTP request)</font><br></font></li><li><font color="#009900">session <font color="#000000">(creates a bean instance for an HTTP Session)</font><br></font></li><li><font color="#009900">application <font color="#000000">(creates the bean instance for the lifecycle of a ServletContext)</font></font></li><li><font color="#009900">websocket <font color="#000000">(creates it for a particular WebSocket session)</font><br></font></li></ul></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-170" y="-1500" width="440" height="130" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-3" value="<b>Bean scopes:</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-140" y="-1510" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-4" value="<div align="left">The last four scopes mentioned, <font color="#009900">request</font>, <font color="#009900">session</font>, <font color="#009900">application </font>and <font color="#009900">websocket</font>, <br></div><div align="left">are only available in a web-aware application.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-140" y="-1375" width="420" height="30" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-6" value="<div align="left"><b>proxyMode </b>attribute is necessary because at the moment of the instantiation of the <br></div><div align="left">web application context, there is no active request.</div><div align="left"><b>@RequestScope </b>annotation can be changed instead<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-140" y="-1235" width="450" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-7" value="<div align="left">@Bean<br>@Scope(value = WebApplicationContext.SCOPE_REQUEST, <br></div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; proxyMode = ScopedProxyMode.TARGET_CLASS)<br><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-130" y="-1305" width="340" height="60" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-11" value="<b>Example</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-140" y="-1340" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-21" value="<font color="#EA6B66"><b><font style="font-size: 85px">Hibernate</font></b></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2650" y="-1640" width="410" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-22" value="<font color="#808080"><b><font style="font-size: 24px">Caches</font></b></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2720" y="-1490" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-23" value="Кэш используется для того чтобы уменьшить количество дорогостоящих обращений в базу данных. " style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2510" y="-1450" width="570" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-24" value="<div align="left"><font style="font-size: 14px"><b>Кеш первого уровня (First-level cache):</b></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-1410" width="280" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-25" value="<div align="left">Кеш первого уровня всегда привязан к <b>объекту сессии</b>. Hibernate всегда по умолчанию использует <br></div><div align="left">этот кеш и его нельзя отключить. (в новых сервисах к <b>EntityManager</b>)<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-1380" width="560" height="30" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-26" value="<div align="left">SharedDoc persistedDoc = (SharedDoc) session.load(SharedDoc.class, docId);<br>System.out.println(persistedDoc.getName());<br>user1.setDoc(persistedDoc);<br><br>persistedDoc = (SharedDoc) session.load(SharedDoc.class, docId);<br>System.out.println(persistedDoc.getName());<br>user2.setDoc(persistedDoc);</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2540" y="-1327.5" width="430" height="100" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-28" value="<div align="left">В этом примере будет выполнен <b>1 запрос в базу</b>, несмотря на то, что делается 2 вызова load(), <br></div><div align="left">так как эти вызовы происходят в <b>контексте одной сессии</b>. Во время второй попытки загрузить <br></div><div align="left">план с тем же идентификатором будет использован <b>кеш сессии.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-1190" width="540" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-29" value="<div align="left">При использовании метода <b>load</b>() Hibernate не выгружает из БД данные до тех пор пока они не <br></div><div align="left">потребуются. Иными словами — в момент, когда осуществляется первый вызов load, мы получаем <br></div><div align="left">прокси объект или сами данные в случае, если данные уже были в кеше сессии. Поэтому в коде ю</div><div align="left">присутствует getName() чтобы 100% вытянуть данные из БД. Тут также открывается прекрасная <br></div><div align="left">возможность для потенциальной оптимизации. В случае прокси объекта мы можем связать два <br></div><div align="left">объекта не делая запрос в базу, в отличии от метода <b>get</b>(). При использовании методов <br></div><div align="left"><b>save</b>(), <b>update</b>(), <b>saveOrUpdate</b>(), <b>load</b>(), <b>get</b>(), <b>list</b>(), <b>iterate</b>(), <b>scroll</b>() всегда будет задействован <br></div><div align="left">кеш первого уровня. Собственно, тут нечего больше добавить.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-1130" width="560" height="120" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-30" value="<div align="left"><font style="font-size: 14px"><b>Кеш второго уровня (Second-level cache):</b></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-990" width="300" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-31" value="<div align="left">Если кеш первого уровня привязан к объекту сессии, то кеш второго уровня привязан к <b>объекту-фабрике <br></b></div><div align="left"><b>сессий (Session Factory object)</b>. Что как бы подразумевает, что <b>видимость этого кеша гораздо шире</b> кеша <br></div><div align="left">первого уровня. Пример:<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-970" width="620" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-32" value="<div align="left">Чтобы включить кэш второго уровня нужно добавить в конфигурационный файл следующее: <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-910" width="520" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-33" value="<div align="left">&lt;property name="hibernate.cache.provider_class" <br></div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/&gt;<br>//или&nbsp; в более старых версиях<br>//&lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider"/&gt;<br>&lt;property name="hibernate.cache.use_second_level_cache" value="true"/&gt;</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="-877" width="540" height="80" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-35" value="<div align="left">Хибернейт сам не реализует кеширование как таковое. А лишь предоставляет структуру для его <br></div><div align="left">реализации. Можно быбрать из списка: <br></div><div align="left"><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-770" width="540" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-36" value="<div align="left">- EHCache<br>- OSCache<br>- SwarmCache<br>- JBoss TreeCache</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-730" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-37" value="<div align="left">Вам также понадобится отдельно настроить и саму <b>реализацию кеша</b>. В случае с <b>EHCache </b>это нужно <br></div><div align="left">сделать в файле <i>ehcache.xml.</i> Ну и в завершение еще нужно указать самому хибернейту, что именно <br></div><div align="left">кешировать. К счастью, это очень легко можно сделать с помощью <b>аннотаций</b>, например так:</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-655" width="590" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-38" value="<div align="left">@Entity<br>@Table(name = "shared_doc")<br>@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)<br>public class SharedDoc{<br>&nbsp;&nbsp;&nbsp; private Set&lt;User&gt; users;<br>}<br><br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="-594" width="340" height="100" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-40" value="<div align="left">После этого второй уровень кэша будет включен и в примере ниже будет выполнен один запрос в базу<br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-480" width="580" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-41" value="<div align="left">Session session = factory.openSession();<br>SharedDoc doc = (SharedDoc) session.load(SharedDoc.class, 1L);<br>System.out.println(doc.getName());<br>session.close();<br><br>session = factory.openSession();<br>doc = (SharedDoc) session.load(SharedDoc.class, 1L);&nbsp; &nbsp;<br>System.out.println(doc.getName());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br>session.close(); <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="-446" width="370" height="130" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-43" value="<div align="left">Хибернейт хранит информацию в виде <b>массивов строк, чисел и т. д</b>. И идентификатор объекта выступает <br></div><div align="left">указателем на эту информацию. Концептуально это нечто вроде Map, в которой id объекта — ключ, <br></div><div align="left">а массивы данных — значение. Приблизительно можно представить себе это так:</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-296" width="610" height="50" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-44" value="<div align="left">1 -&gt; { "Pupkin", 1, null , {1,2,5} }</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="-226" width="180" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-46" value="<div align="left">Что есть очень разумно, учитывая сколько лишней памяти занимает каждый объект.<br>Помимо вышесказанного, следует помнить — <b>зависимости Вашего класса по умолчанию также не <br></b></div><div align="left"><b>кешируются</b>. Например, если рассмотреть класс выше — SharedDoc, то при выборке коллекция <br></div><div align="left">users будет доставаться из БД, а не из кеша второго уровня. Если Вы хотите также кешировать и <br></div><div align="left">зависимости, то класс должен выглядеть так:</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="-192" width="580" height="80" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-47" value="<div align="left">@Entity<br>@Table(name = "shared_doc")<br>@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)<br>public class SharedDoc{<br>&nbsp;&nbsp;&nbsp; @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)<br>&nbsp;&nbsp;&nbsp; private Set&lt;User&gt; users;<br>}</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="-100" width="350" height="100" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-49" value="<div align="left">И последняя деталь — <b>чтение из кеша второго уровня происходит только в том случае</b>, если нужный <br></div><div align="left">объект не был найден в <b>кеше первого уровня</b>.</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="25" width="600" height="30" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-51" value="<div align="left"><font style="font-size: 14px"><b>Кеш запросов (Query cache):</b></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="70" width="210" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-52" value="<div align="left">По умолчанию этот <b>кэш отключен</b>, для включения нужно использовать следующую конфигурацию: <br></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="100" width="560" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-53" value="&lt;property name="hibernate.cache.use_query_cache" value="true"/&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2525" y="140" width="370" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-55" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="184" width="540" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-56" value="<div align="left">Query query = session.createQuery("from SharedDoc doc where doc.name = :name");<br>query.setCacheable(true);</div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2530" y="189" width="470" height="30" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-57" value="<div align="left">Кеш запросов <b>похож на кеш второго уровня</b>. Но в отличии от него — <b>ключом к данным </b>кеша выступает <br></div><div align="left">не идентификатор объекта, <b>а совокупность параметров запроса</b>. А сами данные — это идентификаторы <br></div><div align="left">объектов соответствующих критериям запроса. Таким образом, этот кеш <b>рационально использовать с <br></b></div><div align="left"><b>кешем второго уровня.</b></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="236" width="600" height="60" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-58" value="<b style="font-size: 14px">Стратегии кэширования:</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="310" width="190" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-59" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">- Read-only<br>- Read-write<br>- Nonstrict-read-write<br>- Transactional<br><br></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="370" width="130" height="90" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-61" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">Стратегии кеширования определяют поведения кеша в определенных ситуациях. <br></font></div><div style="font-size: 12px" align="left"><font style="font-size: 12px">Выделяют четыре группы:</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="330" width="460" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-62" value="Что нужно знать:" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="2520" y="460" width="130" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-63" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">Во время разработки приложения, особенно сначала, очень удобно видеть действительно ли кешируются <br></font></div><div style="font-size: 12px" align="left"><font style="font-size: 12px">те или иные запросы, для этого нужно указать фабрике сессий следующие свойства:</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="490" width="600" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-64" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">&lt;property name="hibernate.show_sql" value="true"/&gt;<br>&lt;property name="hibernate.format_sql" value="true"/&gt;</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2525" y="540" width="300" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-66" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">В дополнение фабрика сессий также может генерировать и сохранять статистику использования всех <br></font></div><div style="font-size: 12px" align="left"><font style="font-size: 12px">объектов, регионов, зависимостей в кеше:</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="590" width="580" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-67" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">&lt;property name="hibernate.generate_statistics" value="true"/&gt;<br>&lt;property name="hibernate.cache.use_structured_entries" value="true"/&gt;</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="640" width="400" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-69" value="<font style="font-size: 12px"><br></font><div style="font-size: 12px" align="left"><font style="font-size: 12px">Для этого есть объекты Statistics для фабрики и SessionStatistics для сессии.<br><br>Методы сессии:<br>flush() — синхронизирует объекты сессии с БД и в то же время обновляет сам кеш сессии.<br>evict() — нужен для удаления объекта из кеша cессии.<br>contains() — определяет находится ли объект в кеше сессии или нет.<br>clear() — очищает весь кеш<br><br></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="2520" y="670" width="520" height="160" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-70" value="<font style="font-size: 14px"><b>Summary</b></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" parent="1" vertex="1">
<mxGeometry x="-2064" y="-1471" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-72" value="<div align="left"><font style="font-size: 14px"><b>REST </b>это набор <b>архитектурных принципов постороения распределенных</b></font></div><div align="left"><font style="font-size: 14px"><b>систем</b>, который описывает способы обработки и передачи <b>состояний ресурсов</b></font></div><div align="left"><font style="font-size: 14px"><b>по HTTP. </b><br></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-2064" y="-1451" width="550" height="60" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-73" value="<div style="font-size: 12px" align="left"><font style="font-size: 12px">REST легкий, потому что по сути передает ресурсы, без лишних оберток. <br></font></div><div style="font-size: 12px" align="left"><font style="font-size: 12px">URL запроса является своего рода id ресурса. <br></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-2064" y="-1391" width="420" height="40" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-74" value="<div style="font-size: 12px"><font style="font-size: 12px">Чтобы система считалась Restful она должна быть Client-server, stateless, Cache,</font></div><div style="font-size: 12px"><font style="font-size: 12px">Uniform interface (Identification of resources, Manipulations of resources through</font></div><div style="font-size: 12px"><font style="font-size: 12px">representation, self-descriptive messages, HATEOAS), Layered system,</font></div><div style="font-size: 12px"><font style="font-size: 12px">Code-on-Demand.<br></font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-2064" y="-1351" width="460" height="70" as="geometry" />
</mxCell>
<mxCell id="WsvQsJm2ObX6OhKaBQ0v-75" value="<font style="font-size: 12px"><b>Идемпотентность </b>означает, что </font><font style="font-size: 12px"><b>создание большого <br></b></font><div><font style="font-size: 12px"><b>количества идентичных запросов имеет такой же эффект, как и один запрос.</b></font><br><font style="font-size: 12px"><b><b>PUT </b>и <b>DELETE </b>по определению <b>идемпотентны</b>.</b></font></div><div><font style="font-size: 12px"><b>Методы <b>GET</b>, <b>HEAD</b>, <b>OPTIONS </b>и <b>TRACE </b>определены как безопасные</b> </font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-2064" y="-1289" width="470" height="80" as="geometry" />
</mxCell>
<mxCell id="ZLFHjFFExIw5ZwxmRSem-1" value="Bean lifecycle" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;" vertex="1" parent="1">
<mxGeometry x="660" y="-1500" width="90" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>