**Многопоточность** - это:
- одновременное выполнение нескольких действий (например, отрисовка пользовательского интерфейса и передача файлов по сети)
- ускорение вычислений (при наличии нескольких вычислительных ядер)
  
**Закон Амдала**: $S(N)=\frac{1}{(1-P)+\frac{P}{N}}$, где:
- $S$ - ускорение (speedup)
- $P$ - доля вычислений, которые возможно распараллелить
- $N$ - количество вычислительных ядер
  
Доступ к разделяемому ресурсу:
- Блокировка (mutual exclusion)
- Неблокирующий доступ:
	- Lock-free - гарантированный прогресс приложения
	- Wait-free - гарантированный прогресс каждого потока (каждый поток завершает выполнение любой операции за конечное число шагов)
  
Потоки представлены экземплярами класса `java.lang.Thread`:
- `String getName()`
- `Long getId()`
- `boolean isDaemon()`
- `StackTraceElement[] getStackTrace()`
- `ThreadGroup getThreadGroup()`
#### Создание потоков
Создание потока подкласса `Thread`:
```java
Thread thread = new Thread() {
	@Override
	public void run() {
		//...
	}
}
```
  
```java
import.java.util.*;

public class Main {
	public static void main(String[] args) {
		Thread th1 = new Thread() {
			public void run() {
				System.out.println(getName());
			}
		};
		Thread th2 = new Thread() {
			public void run() {
				System.out.println(getName());
			}
		};
		th1.start();
		th2.start();
		System.out.println("Main thread");
	}
}
```
  
```java
import.java.util.*;

public class Main {
	private static class MyThread implements Runnable {
		public void run() {
			System.out.println(Thread.currentThread().getName());
		}
	}
	public static void main(String[] args) {
		for (int i = 1; i <= 10; i++)
			new Thread(new myThread()).start();
		th1.start();
		th2.start();
		System.out.println("Main thread");
	}
}
```
#### Управление потоками
Управление потоками класса `java.lang.Thread`:
- `start()`
- `sleep()`
- `join()`
- `interrupt()`
- `stop()`
```java
import.java.util.*;

public class Main {
	private static class MyThread implements Runnable {
		public void run() {
			try {
				//Thread.sleep(1000);
				System.out.println(Thread.currentThread());
			}
			catch (InterruptedExceprion ex) {}
		}
	}
	public static void main(String[] args) {
		for (int i = 1; i <= 10; i++) {
			Thread th = new Thread(new myThread());
			th.start();
			th.join();
		}
		System.out.println("Main thread");
	}
}
```
#### Жизненный цикл потока
- **Создание объекта** `Thread`
- **Запуск** - `thread.start()`
- **Работа** - выполняется метод `run()`,  `thread.isAlive() == true`
- **Завершение** - метод `run()` закончился или бросил исключение
- **Завершенный поток нельзя перезапустить**
## Синхронизация
- **Взаимное исключение** - пока один поток что-то делает, другие не могут ему помешать
- **Ожидание и уведомление** - поток ожидает уведомлений от других потоков
#### Взаимное исключение
Ключевое слово `synchronized`:
- Синхронизированный метод:
	```java
	public synchronized void doSomething() {
		//...
	}
	```
- Синхронизированный блок внутри метода:
	```java
	public void doSomething() {
		synchronized(obj) {
			//...
		}
	}
	```
	  
	```java
	public class Main {
		private static class MyThread1 implements 
		Egor eg;
		Thread1(Egor _eg) {eg = _eg}
		public void run() {
			for (int i = 1; i < 100000; i+)
				eg.put(1)
		}
		
		public static void main(String[] args) thread {
			Egor eg = new Egor(10000);
			MyThread1 th1 = new MyThread1(eg);
			MyThread2 th2 = new MyThread2(eg);
			
			th1.start(); th2.start();
			th1.join(); th2.join();
		}
	}
	```
- Синхронизация блоков - по монитору указанного объекта
- Синхронизация методов - по монитору текущего объекта (`this`)
- Синхронизация статических методов - по монитору класса
#### Ожидание и уведомление
Допустимо только внутри `synchronized`
- `void wait()`
- `void wait(long millis)`
- `void wait(long millis, int nanos)`
- `void notify()`
- `void notifyAll()`
## Средства стандартных библиотек. Пакеты `java.util.concurrent`
- Атомные типы
- Примитивы синхронизации
- Коллекции
- Executors
- Parallel Streams
#### Атомные типы. Пакет `java.util.concurrent.atomic`
- `AtomicBoolean`
- `AtomicInteger`
- `AtomicLong`
- `AtomicReference<V>`
  
Операции: 
- `V get()`
- `void set(V newValue)`
- `boolean compareAndSet(V expect, V update)`
  
Пример `AtomicInteger`:
```java
AtomicInteger ai = new AtomicInteger(1);
ai.getAndIncrement();
System.out.println(ai.get());
ai.addAndGet(100);
System.out.println(ai.get());
```
#### Семафоры. Класс `java.util.concurrent.semaphore`
В отличие от `synchronized`-блока, одновременно могут работать несколько потоков (но не более заданного `N`).  
Операции:
- `void acquire()`
- `void release()`
```java
Semaphore semaphore = new Semaphore(10);
semaphore.acquire();
try {
	///...
} finally {
	semaphore.release();	
}
```
#### Класс `java.util.concurrent.CountDownLatch`
Обеспечивает точку синхронизации между `N` потоками (несколько потоков могут дожидаться друг друга и потом стартовать одновременно).  
Операции:
- `void countDown()`
- `void await()`
```java
CountDownLach latch = new CountDownLatch(10);
```
  
```java
private static class MyThread1 implements {
	CountDownLatch latch;
	MyThread1(CountDownLatch _latch) {
		latch = _latch;
		new Thread(this).start();
	}
	public void run() {
		for (int i = 1; i <= 5; i++) {
			System.out.println(i);
			latch.countDown();
		}
	}
}

public static void main(String[] args) throw Exception {
	CountDownLatch cdl = new CountDownLatch(10);
	System.out.println('Потоки исполнения:');
	new MyThread1(cdl);
	new MyThread1(cdl);
	try {
		cdl.await();
	} catch (InterruptedException ex) {
		System.out.println(ex.toString());
	}
	System.out.println("Основной поток завершен")
}
```
#### Класс `java.util.concurrent.CyclicBarrier`
Вариант `CountDownLatch`, допускающий повторное ожидание.
#### Класс `java.util.concurrent.locks.ReentrantLock`
Обеспечивает взаимное исключение потоков, аналогичное `synchronized`-блокам.  
Операции:
- `lock()`
- `unlock()`
```java
Lock lock = new ReentrantLock();
lock.lock();
try {
	doSomething();
} finally {
	lock.unlock();
}
```
#### Класс `java.util.concurrent.locks.Condition`
- Аналог `wait`/`notify`
- Привязан к `Lock`'у
- У одного `Lock`'а может быть много `Condition`'ов
```java
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
	while (!conditionSatisfied()) {
		condition.await();
	}
} finally {
	lock.unlock();
}
condition.signal();
```
## Многопоточные варианты стандартных коллекций
- `ConcurrentHashMap`
- `ConcurrentSkipListMap`
- `ConsurrnetSkipListSet`
- `CopyOnWriteArrayList`
- `CopyOnWriteArraySet`
- и др.
  
Более эффективны, чем полностью синхронизированные коллекции `java.util.Collections.synchronizedCollection()`
## Интерфейс `Executor`
В многопоточный пакет `concurrent` для управления потоками включено средство, называемое сервисом исполнения `ExecutorService`. Данное средство служит альтернативой классу `Thread`, предназначенному для управления потоками. В основу сервиса исполнения положен интерфейс `Executor`, в котором определен один метод.
```java
void execute(Runnable thread)
```
#### Класс `java.util.concurrent.ExecutorService`
Инкапсулирует создание потоков, организацию очереди задач, распределение задач по потокам.  
Операции:
- `Future<?> submit(Runnable task)`
- `<T>Future<T> submit(Callable<T> task)`
- `void shutdown()`
- `List<Runnable> shutdownNow()`
#### Класс `java.util.concurrent.Executors` фабрики класса
- `ExecutorService newSingleThreadExecutor()`
- `ExecutorService newFixedThreadPool(int nThreads)`
- `ExecutorService newCachedThreadPool()`
```java
private static class Main {
	public void run() {
		try {
			System.out.println(getName());
			sleep(2000);
		} catch(InterruptedException ex) {
			//...
		}
	}
}

public static void main(String[] args) throw Exception {
	ExecutorService es = Executors.newFixedThreadPool(3);
	es.execute(new MyThread1());
	es.execute(new MyThread1());
	es.execute(new MyThread1());
	es.execute(new MyThread1());
	es.execute(new MyThread1());
	es.shutdown();
	System.out.println("Основной поток завершен")
}
```
#### Класс `java.util.concurrent.ForkJoinPool`
**Модель `fork-join`** - это метод, в котором мы разделяем каждую задачу (`fork`), а затем ждем объединения (`join`) всех получившихся подзадач и получаем результат.  
Принимает на исполнение `ForkJoinTask`
## Параллельные потоки
- `stream.parallel()`
- Возвращает `stream`, дальнейшие операции в котором будут исполняться параллельно
```java
public static void main(String[] args) throw Exception {
	List<String> list = Arrays.asList("Anna", "Egor", "Temka", "Leha", "Marsik");
	list.stream().filter(p->p.length() == 4).forEach(System.out::println());
	System.out.println("-----------------");
	list.parallelStream().filter(p->p.length() == 4).forEach(System.out::println());
	System.out.println("Основной поток завершен")
}
```