diff --git a/README.md b/README.md
index 127b1304a..e255ebddb 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
- используя асинхронные сервлеты 3.0
- сохранение данных в PostgreSQL используя [jDBI](http://jdbi.org/)
- миграция базы [LiquiBase](http://www.liquibase.org/)
-- использование в проекте [Guava](https://github.com/google/guava/wiki), [Thymleaf](http://www.thymeleaf.org/), [Lombook](https://projectlombok.org/), [StreamEx](https://github.com/amaembo/streamex),
+- использование в проекте [Guava](https://github.com/google/guava/wiki), [Thymleaf](http://www.thymeleaf.org/), [Lombok](https://projectlombok.org/), [StreamEx](https://github.com/amaembo/streamex),
[Typesafe Config](https://github.com/typesafehub/config), [Java Microbenchmark JMH](http://openjdk.java.net/projects/code-tools/jmh)
### Требование к участникам
@@ -38,13 +38,16 @@
> В видео в `LazySingleton` ошибка: должно быть как в коде проекта `instance == null`
### Структура памяти: куча, стек, permanent/metaspace
- - JVM изнутри - оптимизация и профилирование.
+ - JVM изнутри - оптимизация и профилирование.
- Stack and Heap
- Дополнительно:
- Из каких частей состоит память java процесса.
- Permanent область памяти
- Java thread stack
- Размер Java объектов
+ - Оптимизация памяти
+ - [Escape analysis и скаляризация: Пусть GC отдохнет](https://habr.com/company/jugru/blog/322348)
+ - [Условия для размещения объекта в стеке](https://stackoverflow.com/a/43002529/548473)
### Ленивая инициализация
- Реализация Singleton в JAVA
@@ -64,6 +67,7 @@
- Использование ThreadLocal переменных
- Николай Алименков — Прикладная многопоточность
- Can thread switching happen in the synchronized block?
+- [Реактивное программирование - как, зачем и стоит ли?](https://habr.com/ru/company/oleg-bunin/blog/543386/)
#### Tproger: Многопоточное программирование в Java 8
- 1. Параллельное выполнение кода с помощью потоков
@@ -74,9 +78,10 @@
> правка к видео: `22: completionService.submit(..)`
###  Все изменения в проекте будут делаться на основе патчей
-#### Скачайте [1_1_MailService.patch](https://drive.google.com/open?id=0B9Ye2auQ_NsFTE5ZV3pzWElxTWM), положите его в проект, правой мышкой на нем сделайте Apply Patch ...
+#### Скачайте [1_1_MailService.patch](https://drive.google.com/file/d/0B9Ye2auQ_NsFTE5ZV3pzWElxTWM/view?resourcekey=0-TF7H5aadPlE3aQukNC5Ejg), положите его в проект, правой мышкой на нем сделайте Apply Patch ...
----------------------------
+- [Как сделать Java код проще и нагляднее](https://habrahabr.ru/company/wrike/blog/349652/)
### Ресурсы (основы)
- Intuit, Потоки выполнения. Синхронизация
@@ -85,13 +90,16 @@
- Computer Science Center, курс Параллельное программирование
- Юрий Ткач, курс Advanced Java - Concurrency
- Головач, курс Java Multithreading
-
+- [Перевод «Java Memory Model»](https://habr.com/ru/post/510454/)
---
##  Задание первого занятия
Вычекать этот проект:
```git clone https://github.com/JavaOPs/masterjava.git```
+> - [Настройка git на свой репозиторий](https://github.com/JavaOPs/basejava/blob/master/lesson/lesson1.md#настройка-проекта)
+> - [Правила работы с патчами на проекте](https://github.com/JavaOPs/topjava/wiki/Git)
+
- Применить оптимизацию к MatrixUtil.singleThreadMultiply
- Реализовать метод `MatrixUtil.concurrentMultiply`, позволяющий многопоточно перемножать квадратные матрицы N*N.
- Количество дочерних потоков ограничено `MainMatrix.THREAD_NUMBER`.
@@ -99,9 +107,9 @@
-----
##  Подсказки по HW1
-- не делайте 1000 000 тасок, лучше их сделать крупнее
-- у меня разница между 4 и 1000 тасками по времени незаметна, поэтому делайте просто и не делайте сложно
-- наконец: можно не считать значение элемента результирующей матрицы C за раз, а накапливать (`concurrentMultiply3`). Мои результаты:
+- 1: не делайте 1000 000 тасок, лучше их сделать крупнее
+- 2: у меня разница между 4 и 1000 тасками по времени незаметна, поэтому делайте просто и не делайте сложно
+- 3: наконец: можно не считать значение элемента результирующей матрицы C за раз, а накапливать (`concurrentMultiply3`). Тогда трансформация B не нужна. Мои результаты:
```
Benchmark (matrixSize) Mode Cnt Score Error Units
MatrixBenchmark.singleThreadMultiplyOpt 1000 ss 100 837,867 ± 25,530 ms/op
@@ -134,14 +142,14 @@ MatrixBenchmark.concurrentMultiply3 1000 ss 100 186,827 ± 11,882
- Maven. Поиск и разрешение конфликтов зависимостей
- Подключаем логирование с общими настройкам
- Библиотеки и фреймворки для работы с JDBC.
-- Модуль persist
+- Модуль persistence
## Занятие 5
- Разбор ДЗ
- Сохранение в базу в batch-моде с обработкой конфликтов
- Вставка в несколько потоков
- Конфигурирование приложения (Typesafe config)
-- Lombook
+- Lombok
## Занятие 6
- Разбор ДЗ (доработка модели и модуля export)
diff --git a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java b/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java
index 80a344ac2..f64abfbcd 100644
--- a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java
+++ b/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java
@@ -18,19 +18,30 @@ public static int[][] concurrentMultiply(int[][] matrixA, int[][] matrixB, Execu
return matrixC;
}
- // TODO optimize by https://habrahabr.ru/post/114797/
public static int[][] singleThreadMultiply(int[][] matrixA, int[][] matrixB) {
final int matrixSize = matrixA.length;
final int[][] matrixC = new int[matrixSize][matrixSize];
- for (int i = 0; i < matrixSize; i++) {
+
+ int[] thatColumn = new int[matrixSize];
+
+ try {
for (int j = 0; j < matrixSize; j++) {
- int sum = 0;
for (int k = 0; k < matrixSize; k++) {
- sum += matrixA[i][k] * matrixB[k][j];
+ thatColumn[k] = matrixB[k][j];
+ }
+ for (int i = 0; i < matrixSize; i++) {
+ int[] thisRow = matrixA[i];
+ int sum = 0;
+
+ for (int k = 0; k < matrixSize; k++) {
+ sum += thisRow[k] * thatColumn[k];
+ }
+ matrixC[i][j] = sum;
+
}
- matrixC[i][j] = sum;
}
+ } catch (IndexOutOfBoundsException ignored) {
}
return matrixC;
}
diff --git a/src/main/java/ru/javaops/masterjava/service/MailService.java b/src/main/java/ru/javaops/masterjava/service/MailService.java
index 2b6aeb294..cef46e55e 100644
--- a/src/main/java/ru/javaops/masterjava/service/MailService.java
+++ b/src/main/java/ru/javaops/masterjava/service/MailService.java
@@ -1,8 +1,10 @@
package ru.javaops.masterjava.service;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.*;
+import java.util.stream.Collectors;
public class MailService {
private static final String OK = "OK";
@@ -11,10 +13,74 @@ public class MailService {
private static final String INTERRUPTED_BY_TIMEOUT = "+++ Interrupted by timeout";
private static final String INTERRUPTED_EXCEPTION = "+++ InterruptedException";
+ private final ExecutorService mailExecutor = Executors.newFixedThreadPool(8);
+
public GroupResult sendToList(final String template, final Set emails) throws Exception {
- return new GroupResult(0, Collections.emptyList(), null);
- }
+ final CompletionService completionService = new ExecutorCompletionService<>(mailExecutor);
+
+ List> futures = emails.stream()
+ .map(email -> completionService.submit(() -> sendToUser(template, email)))
+ .collect(Collectors.toList());
+ return new Callable() {
+ private int success = 0;
+ private List failed = new ArrayList<>();
+
+ @Override
+ public GroupResult call() {
+ while (!futures.isEmpty()) {
+ try {
+ Future future = completionService.poll(10, TimeUnit.SECONDS);
+ if (future == null) {
+ return cancelWithFail(INTERRUPTED_BY_TIMEOUT);
+ }
+ futures.remove(future);
+ MailResult mailResult = future.get();
+ if (mailResult.isOk()) {
+ success++;
+ } else {
+ failed.add(mailResult);
+ if (failed.size() >= 5) {
+ return cancelWithFail(INTERRUPTED_BY_FAULTS_NUMBER);
+ }
+ }
+ } catch (ExecutionException e) {
+ return cancelWithFail(e.getCause().toString());
+ } catch (InterruptedException e) {
+ return cancelWithFail(INTERRUPTED_EXCEPTION);
+ }
+ }
+/*
+ for (Future future : futures) {
+ MailResult mailResult;
+ try {
+ mailResult = future.get(10, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ return cancelWithFail(INTERRUPTED_EXCEPTION);
+ } catch (ExecutionException e) {
+ return cancelWithFail(e.getCause().toString());
+ } catch (TimeoutException e) {
+ return cancelWithFail(INTERRUPTED_BY_TIMEOUT);
+ }
+ if (mailResult.isOk()) {
+ success++;
+ } else {
+ failed.add(mailResult);
+ if (failed.size() >= 5) {
+ return cancelWithFail(INTERRUPTED_BY_FAULTS_NUMBER);
+ }
+ }
+ }
+*/
+ return new GroupResult(success, failed, null);
+ }
+
+ private GroupResult cancelWithFail(String cause) {
+ futures.forEach(f -> f.cancel(true));
+ return new GroupResult(success, failed, cause);
+ }
+ }.call();
+ }
// dummy realization
public MailResult sendToUser(String template, String email) throws Exception {