docs: public M join()
      {
          if (threadMap.isEmpty())
          {
              throw new IllegalStateException("threads are already interrupted");
          }
          Thread currentThread = Thread.currentThread();
          Semaphore currentSemaphore = semaphoreMap.get(currentThread);
          if (currentSemaphore == null)
          {
              throw new IllegalStateException("Current thread is not workflow thread");
          }
          stopSemaphore.release();
          parallelSet.remove(getCurrentKey());
          return doJoin();
      }