Корутины (Coroutines) — это легковесные потоки, т.е. потоки, исполняемые в рамках одного процесса операционной системы.
Функция launch
запускает новую корутину в указанной области видимости без возврата результата ее выполнения.
launch {
// Данный блок кода содержит инструкции запускаемой корутины
}
Область видимости (Coroutine Scope) позволяет управлять временем жизни корутины и гарантирует, что корутина будет корректно завершена, если область видимости завершит свою работу.
Глобальная область видимости доступна на протяжении всего времени работы приложения.
GlobalScope.launch {
// Запуск корутины в глобальной области видимости
}
Пример запуска корутины в глобальной области видимости:
import kotlinx.coroutines.*
fun main() {
// Запуск корутины в глобальной области видимости
GlobalScope.launch {
// Данный блок кода содержит инструкции запускаемой корутины
delay(1000L) // Неблокирующая задержка на одну секунду
println("World!")
}
// Основной поток продолжает свою работу, не дожидаясь завершения сопрограммы
println("Hello,")
// Блокировка основного потока на две секунды, чтобы дождаться завершения сопрограммы
Thread.sleep(2000L)
}
Результат выполнения:
Hello,
World!
Вызов функции runBlocking
создает область видимости, которая блокирует текущий поток до завершения всех корутин внутри нее.
runBlocking {
launch {
// Запуск корутины в блокирующей области видимости
}
}
Пример запуска корутины в блокирующей области видимости, в результате которого блокируется основной поток:
import kotlinx.coroutines.*
fun main() = runBlocking {
launch { // Запуск корутины в блокирующей области видимости
// Данный блок кода содержит инструкции запускаемой корутины
delay(1000L)
println("World!")
}
println("Hello,")
}
Функция launch
возвращает объект типа Job
(называемый задачей), который можно использовать для управления жизненным циклом корутины (например, для ее отмены или ожидания завершения).
import kotlinx.coroutines.*
fun main() = runBlocking {
// Создаём и запускаем задачу
val job = launch {
delay(1000L)
println("Task completed")
}
}
Вызов функции join
у объекта типа Job
, присоединяет соответствующую корутину к текущему потоку, т.е. потоку из которого вызвана данная функция. Выполнение данной операции приводит к тому, что текущий поток не будет завершен до тех пор, пока не завершится присоединенная к нему корутина.
import kotlinx.coroutines.*
fun main() = runBlocking {
// Создаём и запускаем задачу
val job = launch {
delay(1000L) // Неблокирующая задержка на одну секунду
println("Task completed")
}
println("Task is active: ${job.isActive}") // true
job.join() // Ожидаем завершения задачи
println("Task is completed: ${job.isCompleted}") // true
println("Task is cancelled: ${job.isCancelled}") // false
}
Функции, отмеченные ключевым словом suspend
, могут приостанавливать своё выполнение, не блокируя текущий поток.
import kotlinx.coroutines.*
fun main() = runBlocking {
greeting()
println("I am continue working")
}
// Функция приостановки
suspend fun greeting() {
delay(1000L) // Задержка потока на одну секунду
println("Hello World!")
}
Функция async
запускает корутины с возвратом результата ее выполнения. В отличие от launch
, функция async
возвращает объект типа Deferred<T>
, который позволяет получить результат выполнения корутины.
import kotlinx.coroutines.*
fun main() = runBlocking {
val deferred = async {
delay(1000L) // Имитация асинхронной работы
0 // Возвращение некотрого результата
}
println("Waiting for result...")
val result = deferred.await() // Получение результата
println("Result: $result") // Вывод: "Result: 0"
}
Часть 1
Разработать программу, которая запускает несколько корутин параллельно, для генерации последовательности букв. Программа должна:
- Запускать корутины, каждая из которых генерирует уникальную букву английского алфавита (например, первая корутина генерирует букву "A", вторая — "B", и так далее).
- Выводить сгенерированные буквы в командную строку.
- После завершения всех корутин вывести в командную строку статистику: сколько букв было сгенерировано каждой корутиной.
Часть 2
Разработать программу, которая ищет заданную строку в текстовых файлах параллельно с использованием корутин. Программа должна:
- Принимать путь к директории с текстовыми файлами и строку для поиска.
- Формировать список файлов в данной директории и ее поддиректориях.
- Запускать отдельную корутину поиска строки для каждого файла из списка.
- Выводить результаты поиска: список файлов, содержащих искомую строку, в командную строку.
- Обрабатывать ошибки (например, если файл не найден).
Часть 3
Разработать программу, которая выполняет опрос нескольких серверов (командой ping) параллельно с использованием корутин. Программа должна:
- Принимать список адресов серверов (например, IP-адресов или доменных имен).
- Запускать отдельную корутину для опроса каждого сервера.
- Выводить результаты опроса серверов (доступен/недоступен) в командную строку.
- Обрабатывать ошибки (например, если сервер недоступен или адрес некорректен).