2012-04-26 3 views
3

시간 제한이있는 백그라운드에서 일부 작업을 실행하고 싶습니다. 문제는, 나는 주 스레드를 차단하고 싶지 않다는 것입니다.주 스레드를 차단하지 않고 ExecutorService에 대한 시간 초과

순진 구현은 두 개의 실행 프로그램 서비스를 갖는 것입니다. 하나는 스케줄링/타임 아웃을위한 것이고 두 번째 것은 작업 완료에 대한 책임이 있습니다.

final ExecutorService backgroundExecutor = Executors.newSingleThreadExecutor(); 
final ExecutorService workerExecutor = Executors.newCachedThreadExecutor(); 


backgroundExecutor.execute(new Runnable() { 
    public void run() { 
     Future future = workerExecutor.submit(new Runnable() { 
      public void run() { 
       // do work 
      } 
     }); 
     try { 
      future.get(120 * 1000, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e); 
      future.cancel(true); 
     } catch (ExecutionException e) { 
      logger.error("ExecutionException", e); 
     } catch (TimeoutException e) { 
      logger.error("TimeoutException", e); 
      future.cancel(true); 
     } 
    } 
}); 

다른 해결책이 있습니까?

+0

하나의 단순화는 하나의 스레드가 작업을 수행하고 다른 하나가 스레드를 기다리는 단일 스레드 풀 2 개가 될 것입니다. 그건 적어도 내부 수영장을 저장하지만 그렇지 않으면 많은 도움이되지 않습니다. – Gray

+0

Timer와 Executor 모두에 동시에 태스크를 발행 할 수 있습니까? 하나는 run()에 먼저 들어가므로 잠금 또는 동기화가 시간 초과 및 작업 완료 사이의 중재를 위해 필요할 수 있으므로 각 경우에 올바른 조치가 취해질 수 있습니다. 음 .. 확실하지 않습니다. –

+0

코드에서 Future.get()의 결과를 무시했기 때문에 일부 스레드에서 결과를 기다릴 필요가 있는지 궁금합니다. –

답변

2

한 번만 단일 스레드를 실행하기 위해 ExecutorService가 필요하지 않습니다. 대신 FutureTask를 만들면 오버 헤드없이 동일한 이점을 얻을 수 있습니다.

FutureTask<T> future = new FutureTask<T>(callable); 
Thread thread = new Thread(future); 
thread.start(); 
try { 
    future.get(120 * 1000, TimeUnit.MILLISECONDS); 
} ... 

위 스 니펫의 호출 가능 항목이 사용자의 작업입니다. 당신은 당신이를 통해 호출 가능으로 바꿀 수 있습니다 (당신이 위의 코드 블록에서처럼)의 Runnable이있는 경우 : 그래서, 요약

Callable callable = Executors.callable(runnable, null); 

, 코드가 변경 될 수 있습니다에 :

backgroundExecutor.execute(new Runnable() { 
    public void run() { 

     Runnable myRunnable = new Runnable() { 
      public void run() { 
       // do work 
      } 
     } 

     Callable callable = Executors.callable(myRunnable, null); 

     FutureTask<T> future = new FutureTask<T>(callable); 
     Thread thread = new Thread(future); 
     thread.start(); 

     try { 
      future.get(120 * 1000, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e); 
      future.cancel(true); 
     } catch (ExecutionException e) { 
      logger.error("ExecutionException", e); 
     } catch (TimeoutException e) { 
      logger.error("TimeoutException", e); 
      future.cancel(true); 
     } 
    } 
}); 

집행자를 마침내 막을 필요는 없습니다. 마침내 다른 자원을 마침내 정리할 수도 있습니다.

관련 문제