Concurrency Utilities

  • Набор классов, облегчающих написание многопоточных программ
  • Пакет java.util.concurrent
    • Многопоточные коллекции
    • Управление заданиями
  • Уже были
    • Атомарные переменные (.atomic)
    • Блокировки (.locks)
    • Примитивы синхронизации

Многопоточные очереди

Свойства

  • Массовые операции
  • Особенности
    • Неэффективность произвольного доступа
    • Неатомарность массовых операций

Производитель-потребитель

  • Производитель
    while (true) {
        E e;
        // Создание элемента
        queue.put(e);
    }
    
  • Потребитель
    while (true) {
        E e = queue.take();
        // Обработка элемента
    }
    

Реализации BlockingQueue

Многопоточные отображения (1)

Реализация

«Самокопирующиеся» коллекции

  • Делается копия при записи
    • Частое копирование
    • Редкое изменение
  • Список на массиве
  • Множество на массиве

Другие многопоточные коллекции

Исполнители

  • Интерфейс Executor
  • Возможные варианты выполнения
    • В том же потоке
    • Во вновь создаваемом потоке
    • Пул потоков
    • Наращиваемый пул потоков

Функции и результаты

Исполнители функций

Завершение работы

Реализация исполнителей

Класс Executors

Отклонение заданий

Отложенное исполнение

Общая идея

  • Маленький объем работы
    • Выполнить на месте
  • Большой объем работы
    • Разделить на фрагменты

Разделяемые задания

Пример использования

  • Максимум на списке
    • class Max extends RecursiveTask<Integer> {
          private final List<Integer> data;
          public Max(List<Integer> data) { this.data = data; }
          public Integer compute() {
              int s = data.size();
              if (s == 1) return data.get(0);
              Max m1 = new Max(data.subList(0, s / 2));
              Max m2 = new Max(data.subList(s / 2, s));
              m2.fork();
              return Math.max(m1.compute(), m2.join());
          }
      }
      

Реализация

  • Класс ForkJoinPool
    • Выполнение заданий внутри
    • Приоритет локальным заданиям
    • «Кража» крупных заданий
  • Методы
  • Пример
    • final Max task = new Max(data);
      ForkJoinPool.commonPool().execute(task);
      Integer max = task.get();
      

Виртуальные потоки

  • Поток исполнения
  • Не системный
  • Исполняется в рамках системного
    • Возможно — разных
  • Состав
    • Стек
    • Thread locals

История

  • Java 1.1‒1.3: Green threads
  • Java 1.4: Системные потоки
  • Java 19, 20: Preview
  • Java 21: Release

Использование

  • Поток-на-запрос
  • Без пулинга
  • Короткое время жизни

Пример

  • Создание 10 000 потоков
    try (
      ExecutorService executor = Executors
          .newVirtualThreadPerTaskExecutor()
    ) {
        IntStream.range(0, 10_000).forEach(i -> {
            executor.submit(() -> {
                Thread.sleep(Duration.ofSeconds(1));
                return i;
            });
        });
    }
    

Ресурсы

  • Реальный поток для исполнения
  • Ничего при ожидании
    • Ввод-вывод, очереди, future
      // +
      response.send(
          future1.get() // ‒
          +                   // +
          future2.get() // ‒
      ); // +
      
  • Препятствия
    • synchronized
    • native

Создание потоков

Дополнительные возможности

Содержание

Интервалы времени

Очереди с задержкой

Асинхронное вычисление

Очереди заданий

Потокобезопасные коллекции

Ссылки

Вопросы