0

이 질문은 Java 동시성 주제의 숙제와 관련이 있습니다. 새로운 스레드를 생성하고 주어진 스레드 수를 제한하는 작업이 주어진 concurrencyFactor입니다. 즉, 활성 스레드 수가 concurrencyFactor 이하가 될 때까지 새 스레드를 계속 보냅니다. 활성 스레드 수가 concurrencyFactor이면 활성 스레드 수가 concurrencyFactor - 1으로 줄어들 때까지 프로그램이 대기하고 새 스레드를 만듭니다.Java 동시성 : 실행기 동작을 달성하기 위해 래치/ThreadGroup 수정

첫 번째 방법으로 ExecutorService을 사용하고 Executors.newFixedThreadPool(concurrencyFactor);으로 새 고정 풀을 만들고 내 메서드가 호출 될 때마다이 풀에 새 실행 파일을 제출할 때입니다. 논리에 대한 코드는 다음과 같습니다.

private final ExecutorService fixedPoolExecutor = Executors.newFixedThreadPool(concurrencyFactor); 
    public void handleRequest(final RequestHandler handler) { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 
    fixedPoolExecutor.submit(new Runnable() { 
     @Override 
     public void run() { 
      handler.serviceRoutine(); 
     } 
     }); 
    } 

이제 두 번째 부분에서는 집행자를 사용하지 않고 동일한 목표를 달성하도록 요청합니다. (
1) countDownLatch를 사용하지만,이 래치 기다릴 것 즉 latch.await())를 activeCount0 될 때까지 : 나는 두 가지 방법을 다음과 같은 생각을했다.. countDown이 concurrencyFactor - 1이 될 때까지만 기다리고 싶습니다.
2) ThreadGroup을 사용하고 threadGroup.activeCount() < concurrencyFactor까지 기다리십시오. 그러나이 방법의 문제점은 threadGroup.activeCount() < concurrencyFactor 조건이 충족 될 때까지 들어오는 요청을 대기 상태로 만들 수 있습니까? 이 접근법에 대해 아래의 코드를 사용했습니다.

private final Lock lock = new ReentrantLock(); 
    private final ThreadGroup threadGroup = new ThreadGroup("myGroup"); 
    public void handleRequest(final RequestHandler handler) { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 
    lock.lock(); 
    try { 
     while (threadGroup.activeCount() >= concurrencyFactor) { 

     } 
     Thread t = new Thread(threadGroup, new Runnable() { 
      @Override 
      public void run() { 
       handler.service(); 
      } 
     }); 
     t.start(); 
    } finally { 
     lock.unlock(); 
    }   
    } 

두 번째 접근 방법에서 일부 대기 조건으로 루프를 바꾸면서 교체 할 수 있습니까?

위의 접근법에 대한 제안이나 새로운 접근법에 대한 조언은 인정 될 것입니다.

+0

는 할당 힘 당신은 해, CountDownLatch를 사용 하는가 (당신이 가능 중단 다르게 처리 할 수 ​​있습니다)? – bowmore

+0

아니요. 강제하지 않습니다. 그러나 명령은 래치/스레드/실행기를 사용하여이를 달성 할 힌트를 제공합니다. –

+1

세마포어에 적합하기 때문에. – bowmore

답변

1

Sempahore을 사용하는 것이 좋습니다. 세마포어는 아직 시작하도록 허용 된 스레드 수를 나타냅니다. 처음에는 구성된 동시성 요소와 동일한 허가를 보유합니다.

새 스레드를 시작하기 전에 handleRequest 메서드는 세마포어에서 허가를 얻어야합니다. 시작되는 스레드는 완료 허용시 다시 허용되어야합니다.

샘플 코드 :

private final ThreadGroup threadGroup = new ThreadGroup("myGroup"); 
private final Semaphore concurrencyFactor = new Semaphore(CONCURRENCY_FACTOR); 

public void handleRequest(final RequestHandler handler) throws InterruptedException { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 

    concurrencyFactor.acquire(); // Get permit 

    Thread t = new Thread(threadGroup, new Runnable() { 
     @Override 
     public void run() { 
      try { 
       handler.service(); 
      } finally { 
       concurrencyFactor.release(); // make sure to release permit 
      } 
     } 
    }); 
    t.start(); 
} 

+0

이것은 완벽하게 작동합니다. 감사합니다 :) –

+0

run 메소드 내부의 try 블록은'service' 메소드가 완료 될 때까지'concurrencyFactor'가 해제된다는 것을 보장합니까? –

+0

service()에 던져진 예외가 있음에도 불구하고 허가가 해제되도록 보장합니다. – bowmore