Thread

Thread

API для потоков, которыми управляет JVM и ОС. Наследуется от Runnable. Поток закончит выполнение когда завершится его метод run.

val thread = Thread(
    object: Runnable {
        override fun run() {
            // выполнение нового потока
        }
    }
)
thread.start()
isDaemon

Потоки-демоны используются для выполнения фоновых задач обслуживающих процесс в течение его жизни. Если завершается последний обычный поток в процессе - потоки-демоны будут завершены принудительно.

val thread = Thread {}
thread.isDaemon = true
thread.start()
interrupt

Метод прерывания потока. Методы приостанавливающие выполнение потока sleep wait join при вызове прерывания сгенерируют InterruptedException.

val thread = Thread {}
thread.interrupt() // прервать поток
thread.isInterrupted // проверить прерван ли поток. вызывается только изнутри потока
Thread.sleep

Приостанавливает выполнение потока в котором был вызван. Во время выполнения метода sleep система перестает выделять потоку процессорное время распределяя его между другими потоками. Выполняется либо указанное количество времени либо пока не будет остановлен прерыванием.

val thread = Thread {
    Thread.sleep(1000L)
}
Thread.yield

Переключает процессор на обработку других потоков.

while (!msgQueue.hasMessages()) { // пока в очереди нет сообщений
    Thread.yield() // передать управление другим потокам
}
join

Механизм позволяющий одному потоку ждать завершения выполнения другого. В параметр можно указать время ожидания.

thread.join() // возвращает управление когда завершится ожидаемый поток
thread.join(1000L) // возвращает управление когда завершится ожидаемый поток или закончится время
Priority

Каждый поток в системе имеет свой приоритет. Система в первую очередь выполняет потоки с большим приоритетом, а потоки с меньшим приоритетом получают процессорное время только тогда, когда их более привилегированные собратья простаивают.

MIN_PRIORITYМинимальный приоритет.
NORM_PRIORITYДефолтный умолчанию.
MAX_PRIORITYМаксимальный приоритет.
thread.priority = Thread.MAX_PRIORITY
isAlive

Возвращает true если поток выполняется и false если поток завершен или не был запущен.

thread.isAlive
name

Задать имя потока. Помогает понять какой поток выполняет некоторое действие.

thread.name = "MyThread"
id

Возвращает идентификатор потока. Это уникальное число присвоенное потоку.

thread.id
Thread.currentThread

Возвращает объект потока в котором вызван.

val thread = Thread {
    Thread.currentThread()
}
Вопросы на собесе (9)
  1. Как создать новый поток с использованием класса Thread?

    Создать подкласс Thread или передать объект Runnable в конструктор Thread. Затем вызвать start() для запуска потока.

  1. Зачем нужен метод join и когда его следует использовать?

    Метод join заставляет текущий поток ждать завершения другого потока, чтобы убедиться, что его выполнение завершилось до продолжения работы текущего потока.

  1. Как управлять приоритетом потоков в Java?

    Приоритет потоков в Java управляется методом setPriority класса Thread, который принимает значения от Thread.MIN_PRIORITY до Thread.MAX_PRIORITY.

  1. Как работают методы yield и interrupt?

    yield приостанавливает текущий поток, чтобы другие потоки могли выполниться.

    interrupt прерывает выполнение потока и вызывает InterruptedException, если поток заблокирован.

  1. Что будет со 2 потоком который пытается получить доступ к ресурсу занятым 1 потоком?

    Будет ждать, пока 1 освободит ресурс.

  1. Ресурс занят 1 потоком. 2 и 3 хотят получить доступ, какой из них получит?

    Любой из них.

  1. Почему доступ к освободившемуся ресурсу получает рандомный поток, а не первый в очереди?

    Из-за особенностей реализации синхронизации в JVM. Это связано с использованием стратегий, которые не гарантируют порядок FIFO, оптимизацией производительности и состоянием потоков, что влияет на выбор пробуждаемого потока.

  1. Как пробудить поток, чтобы он перестал ждать доступа к ресурсу?

    Вызвать методы notify() или notifyAll() на объекте блокировки.

  1. Корректно ли написан код будет ли работать?
    class Scheduler {
        
        val jobs = mutableListOf<() -> Unit>()
        
        init {
            thread {
                while (true) {
                    for (job in jobs) job()
                }
            }
        }
    
        fun schedule(job: () -> Unit) {
            jobs += job
        }
    }
    
    val sch = Scheduler()
    thread { sch.schedule { println("hello") } }
    thread { sch.schedule { println("world") } }

    Код не корректен из-за отсутствия синхронизации при доступе к jobs, что может привести к ошибкам, и бесконечного цикла без задержек, что перегружает процессор.