Thread(Поток)
    
    
        Что это
        Thread - класс для создания многопоточной работы в JAVA.
    
    
    
        Thread static методы:
        
            - currentThread() - возвращает текущий поток. Можно получить id/имя потока, сделать join() и тд.
 
            - sleep() - останавливает поток на количество переданных миллисекунд. Поток переходит в состояние TIMED_WAITING.
 
            - interrupted() - прервать поток. Если он вызван во время сна, бросится исключение.
 
        
    
    
        Thread методы(после получения через currentThread()):
        
            - void run() - описывает реализацию работы потока. При запуске - выполнит в том же потоке.
 
            - start() - запускает выполнение метода run, в отдельном потоке.
 
            - long getId()
 
            - String getName()
 
            - join() - приостанавливает поток до завершения другого(переданного) потока.
 
            - join(final long millis) - join() с указание времени, по завершению которого проток продолжиться без ожидания.
 
            - void setPriority(int priority) - задать приоритет потока.
 
            - int getPriority() - получить приоритет потока.
 
        
        Exception который появился в отдельном потоке не вернется в main поток. По этому должен быть обработан
            в своём потоке.
        
    
    
        Планировщик потоков
        Планировщик потоков - часть JVM, решает какой поток должен выполнится в каждый конкретный момент времени
            и какой поток нужно приостановить. И меняет им состояния.
        
        Гарантии:
        
            - Java НЕ гарантирует, что потоки будут выполнены в том порядке в котором они были запущены.
 
            - Нет гарантии, что если поток начал свое выполнение, то он выполнит свою работу не прерываясь.
 
            - При каждом новом запуске программы, результат может быть разным.
 
            - Гарантируется, что каждый поток начнет свою работу и будет выполнять пока не закончит.
 
            - Внутри одного потока действия выполняются в предсказуемом порядке.
 
        
        Методы позволяющие влиять на планировщика потоков
        
            java.lang.Thread
            - public static void sleep(long millis) throws InterruptedException
 
            - public static void yield()
 
            - public final void join() throws InterruptedException
 
            - public final void setPriority(int newPriority)
 
            java.lang.Object
            - public final void wait() throws InterruptedException - выйди из синхронного блока, освободить монитор,
                остановиться перед ним, получить статус waiting, вызвать метод notify().
            
 
            - public final void notify() - разбудит первого в очереди(массив) монитора.
 
            - public final void notifyAll()
 
        
    
    
        Thread.priority
        Priority - приоритет используется для очередности переданных задач. Но это не заблокирует задачи с малым
            приоритетом, они просто будут выполняться реже.
        
        Каждому потоку исполнения в Java присваивается свой приоритет от 1 до 10(5 по умолчанию), который определяет
            поведение данного потока по отношению к другим потокам в планировщике потоков.
        
    
    
        Состояние потока
        
            - new - поток создан, но не запущен.
 
            - runnable - поток выполняется JVM.
 
            - blocked - потом заблокирован, и ждет освобождения монитора.
 
            - waiting - в этом состоянии находится поток, который бесконечно ожидает выполнения другим потоком
                определенного действия.
            
 
            - timed_waiting - в этом состоянии находится поток, ожидающий выполнения действия другим потоком в течение
                указанного времени ожидания.
 
            - terminated - поток завершен. Также потоки не могут быть запущены повторно.
 
        
    
    
        Daemon
        Daemon - поток-демон. Поток, который работает в фоновом режиме и не блокирует завершение программы.
        Создаётся путем переключение переменой boolean методом setDaemon(), перед запуском потока(start()).
        isDaemon() - метод для проверки потока, демон или нет.
        Может создавать только потоки-демоны. Даже если явно не указывать setDaemon().
        Завершают run() без выполнение finally{}.
        Завершаются немедленно(не ждет конца выполнения) - при завершении всех потоков не демонов.
    
    
        ThreadLocal
        ThreadLocal - специальный механизм, позволяющий каждому потоку иметь свою собственную копию переменной,
            изолированную от других потоков.
        
        
ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(100); // Устанавливается только для текущего потока
Integer value = threadLocal.get(); // Получает значение текущего потока
        
        Когда использовать
        
            - Нужна потоковая изоляция без синхронизации. Когда данные должны быть уникальны для каждого потока,
                но не хочется использовать synchronized.
            
 
            - Переменные на время жизни потока. Например, хранение ID запроса, транзакции, даты, пользователя и т. д.,
                которые нужны во многих местах, но только для текущего потока.
            
 
            - В Web-приложениях. Хранение текущего пользователя или сессии без передачи параметров по цепочке методов.
 
            - При работе с небезопасными объектами. Например, SimpleDateFormat не является потокобезопасным, но с
                ThreadLocal его можно безопасно использовать.
            
 
        
        Важно: подводные камни
        
            - Утечки памяти: особенно в сервлет-контейнерах (Tomcat), если ThreadLocal не очищать после использования
                (remove()).
            
 
            - Не подходит для передачи между потоками: каждый поток видит только свою копию.