2009-08-05 5 views

답변

3

일반적으로 스레드 코드에서 컨트롤 개체를 정기적으로 폴링합니다. 뭔가 같은 :

interface ThreadControl { 
    boolean shouldContinue(); 
} 

class Timer implements ThreadControl { 
    public boolean shouldContinue() { 
     // returns false if max_time has elapsed 
    } 
} 

class MyTask implements Runnable { 
    private tc; 
    public MyTask(ThreadControl tc) { 
     this.tc = tc; 
    } 
    public void run() { 
     while (true) { 
      // do stuff 
      if (!tc.shouldContinue()) 
       break; 
     } 
    } 
} 
5

에 대해 어떻게 :

당신의 CallableExecutorService에 제출하고 반환 된 Future에 대한 핸들을 유지한다.

ExecutorService executorService = ... // Create ExecutorService. 
Callable<Result> callable = new MyCallable(); // Create work to be done. 
Future<Result> fut = executorService.submit(callable); 

랩을 DelayedgetDelay(TimeUnit) 방법은 해당 작업에 대한 최대 실행 시간을 반환함으로써 Delayed의 구현에 Future을.

public class DelayedImpl<T> implements Delayed { 
    private final long maxExecTimeMillis; 
    private final Future<T> future; 

    public DelayedImpl(long maxExecTimeMillis, Future<T> future) { 
    this.maxExecMillis = maxExecMillis; 
    this.future = future; 
    } 

    public TimeUnit getDelay(TimeUnit timeUnit) { 
    return timeUnit.convert(maxExecTimeMillis, TimeUnit.MILLISECONDS); 
    } 

    public Future<T> getFuture() { 
    return future; 
    } 
} 

DelayedImpl impl = new DelayedImpl(3000L, fut); // Max exec. time == 3000ms. 

Add the `DelayedImpl` to a `DelayQueue`. 

Queue<DelayedImpl> queue = new DelayQueue<DelayImpl>(); 
queue.add(impl); 

는 큐에서 반복적으로 take() 스레드를 가지고 각 DelayedImplFutureisDone()를 호출하여 완료 여부를 확인; 그렇지 않으면 작업을 취소하십시오.

new Thread(new Runnable() { 
    public void run() { 
    while (!Thread.interrupted) { 
     DelayedImpl impl = queue.take(); // Perform blocking take. 
     if (!impl.getFuture().isDone()) { 
     impl.getFuture().cancel(true); 
     } 
    } 
    } 
}).start(); 

이 방법의 가장 큰 장점은 자동으로 실행 시간의 작은 금액이 남은 작업을 반환 작업 및 지연 큐 당 다른 최대 실행 시간을 설정할 수 있다는 것입니다.

+0

Future.get (Long timeout, TimeUnit unit)은 TimeoutException을 throw합니다. future.cancel (true)를 호출하는 예외에 대한 추정치입니다. – JeeBee

+0

Future.get (long, TimeUnit)은 * 특정 * Future가 완료 될 때까지 지정된 시간 동안 차단됩니다. 그러나 내가 추가 한 솔루션을 사용하면 특정 스레드에서 * 차단 *이 아닌 진행중인 모든 Callable을 확인하는 단일 스레드를 가질 수 있습니다. 5 분이 걸릴 Callable을 제출한다고 가정합니다. 내 "수표"스레드에서 future.get (5L, TimeUnit.MINUTES)을 호출합니다. 다른 Callable은 10 초의 최대 실행 시간으로 제출됩니다. 그러나 스레드는 이전 차단 호출이 반환 될 때까지이 두 번째 Callable이 10 초 이상 실행되었는지 여부를 확인하지 않습니다. – Adamski

4

아담 스키 :

내가 지연된 인터페이스의 구현이 제대로 작동하기 위해서는 약간의 조정이 필요하다고 생각합니다. 오브젝트의 인스턴스 생성으로부터 경과 한 시간이 최대 유효 기간을 초과하면 'getDelay()'의 리턴 값은 음의 값을 리턴해야합니다. 이를 달성하기 위해서는 작업이 생성 된 (그리고 아마도 시작된) 시간을 저장해야합니다. 그런 다음 'getDelay()'가 호출 될 때마다 스레드의 최대 수명이 초과되었는지 여부를 계산합니다. 마찬가지로 :

class DelayedImpl<T> implements Delayed { 

    private Future<T> task; 
    private final long maxExecTimeMinutes = MAX_THREAD_LIFE_MINUTES; 
    private final long startInMillis = System.currentTimeMillis(); 

    private DelayedImpl(Future<T> task) { 
     this.task = task; 
    } 

    public long getDelay(TimeUnit unit) { 
     return unit.convert((startInMillis + maxExecTimeMinutes*60*1000) - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 
    } 

    public int compareTo(Delayed o) { 
     Long thisDelay = getDelay(TimeUnit.MILLISECONDS); 
     Long thatDelay = o.getDelay(TimeUnit.MILLISECONDS); 
     return thisDelay.compareTo(thatDelay); 
    } 

    public Future<T> getTask() { 
     return task; 
    } 
} 
관련 문제