All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.camunda.zeebe.scheduler.ActorThreadGroup Maven / Gradle / Ivy

The newest version!
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
 * one or more contributor license agreements. See the NOTICE file distributed
 * with this work for additional information regarding copyright ownership.
 * Licensed under the Camunda License 1.0. You may not use this file
 * except in compliance with the Camunda License 1.0.
 */
package io.camunda.zeebe.scheduler;

import io.camunda.zeebe.scheduler.ActorScheduler.ActorSchedulerBuilder;
import io.camunda.zeebe.util.Loggers;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;

/**
 * A thread group is a group of threads which process the same kind of tasks (ie. blocking I/O vs.
 * CPU bound).
 */
public abstract class ActorThreadGroup {
  protected final String groupName;
  protected final ActorThread[] threads;
  protected final WorkStealingGroup tasks;
  protected final int numOfThreads;
  private final String schedulerName;

  public ActorThreadGroup(
      final String groupName,
      final int numOfThreads,
      final ActorSchedulerBuilder builder,
      final String schedulerName) {
    this.groupName = groupName;
    this.numOfThreads = numOfThreads;
    this.schedulerName = schedulerName;

    tasks = new WorkStealingGroup(numOfThreads);

    threads = new ActorThread[numOfThreads];

    for (int t = 0; t < numOfThreads; t++) {
      final String threadName = String.format("%s-%d", groupName, t);
      final ActorThread thread =
          builder
              .getActorThreadFactory()
              .newThread(
                  threadName,
                  t,
                  this,
                  tasks,
                  builder.getActorClock(),
                  builder.getActorTimerQueue(),
                  builder.isMetricsEnabled(),
                  builder.getIdleStrategySupplier().get());

      threads[t] = thread;
    }
  }

  public void submit(final ActorTask actorTask) {
    final ActorThread current = ActorThread.current();
    if (current != null && current.getActorThreadGroup() == this) {
      tasks.submit(actorTask, current.getRunnerId());
    } else {
      final int threadId = ThreadLocalRandom.current().nextInt(numOfThreads);
      tasks.submit(actorTask, threadId);
      threads[threadId].hintWorkAvailable();
    }
  }

  public void start() {
    for (final ActorThread actorThread : threads) {
      actorThread.start();
    }
  }

  public String getSchedulerName() {
    return schedulerName;
  }

  public CompletableFuture closeAsync() {
    Loggers.ACTOR_LOGGER.debug("Closing actor thread ground '{}'", groupName);

    final CompletableFuture[] terminationFutures = new CompletableFuture[numOfThreads];

    for (int i = 0; i < numOfThreads; i++) {
      final ActorThread thread = threads[i];
      try {
        terminationFutures[i] = thread.close();
      } catch (final IllegalStateException e) {
        Loggers.ACTOR_LOGGER.error(
            "Closing actor thread ground '{}'. Failed to close thread {}",
            groupName,
            thread.getRunnerId(),
            e);
        terminationFutures[i] = CompletableFuture.completedFuture(null);
      }
    }

    return CompletableFuture.allOf(terminationFutures)
        .thenAccept(
            ok ->
                Loggers.ACTOR_LOGGER.debug(
                    "Closing actor thread ground '{}': closed successfully", groupName));
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy