title: Hystrix thread-isolation based on Group Key or Command name?
body: <p>I noticed that Hystrix has two thread-isolation strategy: Thread and Semaphore.</p>
  
  <p>By default Hystrix used Thread strategy and controls it by <code>hystrix.threadpool.default.coreSize</code> and because of ca ommand with same group key will use the same thread pool. So it is based on group key.</p>
  
  <p>When Hystrix is using Semaphore strategy, the Semaphore will save in a <code>ConcurrentHashMap</code> and the key is command name, will it be based on command name? </p>
  
  <p>Here is the code:</p>
  
  <pre><code>/**
   * Get the TryableSemaphore this HystrixCommand should use for execution if not running in a separate thread.
   *
   * @return TryableSemaphore
   */
  protected TryableSemaphore getExecutionSemaphore() {
    if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.SEMAPHORE) {
      if (executionSemaphoreOverride == null) {
        TryableSemaphore _s = executionSemaphorePerCircuit.get(commandKey.name());
        if (_s == null) {
          // we didn't find one cache so setup
          executionSemaphorePerCircuit.putIfAbsent(commandKey.name(), new TryableSemaphoreActual(properties.executionIsolationSemaphoreMaxConcurrentRequests()));
          // assign whatever got set (this or another thread)
          return executionSemaphorePerCircuit.get(commandKey.name());
        } else {
          return _s;
        }
      } else {
        return executionSemaphoreOverride;
      }
    } else {
      // return NoOp implementation since we're not using SEMAPHORE isolation
      return TryableSemaphoreNoOp.DEFAULT;
    }
  }
  </code></pre>
  
  <p>Why they have difference scope? I write some testing code to prove it:</p>
  
  <pre><code>public static void main(String[] args) throws InterruptedException {
    int i = 0;
    while (i++ &lt; 20) {
      final int index = i;
      new Thread(() -&gt; {
        System.out.println(new ThreadIsolationCommand(index).execute());
        System.out.println(new SemaphoreIsolationCommand(index).execute());
      }).start();
    }
  }
  
  static class ThreadIsolationCommand extends HystrixCommand&lt;String&gt; {
  
    private int index;
  
    protected ThreadIsolationCommand(int index) {
      super(
          Setter
              .withGroupKey(HystrixCommandGroupKey.Factory.asKey("ThreadIsolationCommandGroup"))
              .andCommandKey(HystrixCommandKey.Factory.asKey(String.valueOf(index)))
              .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                  .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
              )
              .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                  .withCoreSize(10)
              )
      );
      this.index = index;
    }
  
    @Override
    protected String run() throws Exception {
      Thread.sleep(500);
      return "Hello Thread " + index;
    }
  
    @Override
    protected String getFallback() {
      return "Fallback Thread " + index;
    }
  }
  
  static class SemaphoreIsolationCommand extends HystrixCommand&lt;String&gt; {
  
    private int index;
  
    protected SemaphoreIsolationCommand(int index) {
      super(
          Setter
              .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SemaphoreIsolationCommandGroup"))
              .andCommandKey(HystrixCommandKey.Factory.asKey(String.valueOf(index)))
              .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                  .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
                  .withExecutionIsolationSemaphoreMaxConcurrentRequests(10)
              )
      );
      this.index = index;
    }
  
    @Override
    protected String run() throws Exception {
      Thread.sleep(500);
      return "Hello Semaphore " + index;
    }
  
    @Override
    protected String getFallback() {
      return "Fallback Semaphore " + index;
    }
  }
  </code></pre>
  
  <p>This command with same group key and different name, result is :</p>
  
  <pre><code>Fallback Thread 9
  Fallback Thread 1
  Fallback Thread 8
  Fallback Thread 19
  Fallback Thread 20
  Fallback Thread 14
  Fallback Thread 3
  Fallback Thread 13
  Fallback Thread 17
  Fallback Thread 10
  Hello Thread 5
  Hello Semaphore 17
  Hello Semaphore 14
  Hello Thread 2
  Hello Semaphore 3
  Hello Thread 7
  Hello Thread 15
  Hello Thread 4
  Hello Semaphore 13
  Hello Semaphore 1
  Hello Thread 11
  Hello Semaphore 20
  Hello Semaphore 19
  Hello Thread 18
  Hello Thread 12
  Hello Semaphore 8
  Hello Semaphore 9
  Hello Thread 6
  Hello Thread 16
  Hello Semaphore 10
  Hello Semaphore 5
  Hello Semaphore 2
  Hello Semaphore 7
  Hello Semaphore 15
  Hello Semaphore 4
  Hello Semaphore 11
  Hello Semaphore 12
  Hello Semaphore 6
  Hello Semaphore 18
  Hello Semaphore 16
  </code></pre>
  
  <p>Only Thread strategy has failed. Is that right?</p>