2013-10-07 3 views
0

내가 제어 할 수없는 레거시 라이브러리와 통합 중입니다.실패한 선물 처리 방법

는 그것은 다음과 같은 인터페이스를 정의하고있다 :

interface Factory { 
    Future<Void> subscribe(Context c); 
} 

이 "가입"방법은 자주 서로 다른 쓰레드에 의해 호출됩니다. "Future.get()"의 결과가 걱정되는 유일한 상황은 실패 할 때이므로 예외를 처리 할 수 ​​있습니다. 호출 스레드에서 발생하지 않아도됩니다. 또한, "Future.get()"에서 호출 스레드를 차단하는 것이 내 경우에 상당히 비쌀 수 있습니다. 성공하더라도 fullfill을 수행하는 데 수초가 걸릴 수 있습니다.

내 작업은 이러한 모든 미래를 "처리 후"실패한 것부터 필터링하는 것입니다.

접근 # 1 : 기본적으로,이 두 가지 접근 방식 볼 수 있습니다

executor.submit(
     new Runnable(){ 
      @Override 
      public void run() { 
       try { 
        future.get(); 
       } catch(Exception e){ 
        // process the exception 
       } 
      } 
     } 
    ); 

단점 : 미래의 인스턴스를 얻기에

을 요구를 할 것이다 외부 집행에 별도의 Runnable 제출 이 접근 방식은 잠재적으로 오랜 시간 동안 스레드를 차단하고 있다는 것입니다. 그리고 내가 말했듯이이 코드 스 니펫은 다소 빈번하게 실행됩니다.

접근 방법 # 2 :

while(true){ 
     Iterator<Future<Void>> iterator = collection.iterator(); 
     while(iterator.hasNext()){ 
      Future<Void> future = iterator.next(); 
      if(future.isDone()){ 
       try { 
        future.get(); 
       } catch(Exception e){ 
        // process the exception 
       } finally { 
        iterator.remove(); 
       } 
      } 
     } 

     TimeUnit.MILLISECONDS.sleep(1000); // sleep 
    } 

: 미래의 인스턴스를 얻는 몇 가지 컬렉션에 배치하고 주기적으로 처리를하고있는이 컬렉션의 요소를 통해 실행하는 별도의 단일 스레드 헌신에

어떻게 생각해? 문제를 해결하는 더 좋은 방법이 있습니까?

답변

1

Future을 만들지 않으므로 최선의 방법을 사용할 수 없으므로 사용자 지정된 Future을 사용하여 Future에서 처리를 시작하십시오.

귀하의 경우 두 가지 옵션이 혼합 된 패턴을 권장합니다. Future을 스레드 안전 큐에 추가하고 루프의 모든 항목을 처리하는 실행 프로그램에 Runnable을 제출하십시오. 따라서 Executor을 구성하여 스레드 수를 제한 할 수 있습니다. 즉, Future만큼 많은 스레드가 없지만 둘 이상 가질 수 있으며 이러한 후 처리 스레드를 항상 유지해야 할 필요가 없습니다. 그래서 Runnable 확인한다

static BlockingQueue<Future<?>> PENDING = …; 
static int MAX_ITEMS_PER_JOB = …; 
… 
/*scheduling code …*/new Runnable() { 
    public void run() 
    { 
    ArrayList<Future<?>> myLocalItems=new ArrayList<>(); 
    PENDING.drainTo(myLocalItems, MAX_ITEMS_PER_JOB); 
    for(Future<?> f:myLocalItems) { 
     if(!f.isDone()) PENDING.offer(f); // re-queue 
     try { 
     f.get(); 
     } catch(ExecutionException ex) { 
     handleException(ex.getCause()); 
     } 
    } 
    } 
}; 

Future 제한된 수의 프로세스 : 다시 큐 미완성 항목, 다시 대기중인 항목에서 보류 분리 로컬 컬렉션을 사용할 때 무한 루프를 방지하기 위해

그래서 많은 항목이 보류 중이면 병렬 처리를 수행하기 위해 여러 번 제출하는 것이 적합하지만 더 적은 숫자가 대기 중이면 아무런 해가되지 않으면 작업이 중단되지 않으므로 아무런 해가되지 않습니다. 그들은 ScheduledExecutorService을 사용하는 scheduleWithFixedDelay에 적합합니다.