2009-08-05 21 views

Odpowiedz

3

Zazwyczaj po prostu odpytywam obiekt kontrolny z kodu gwintowanego. Coś jak:

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

Jak o:

zgłosić swoją Callable do ExecutorService i trzymać rączkę do zwracanego Future.

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

zawinąć Future w realizacji Delayed czym Delayed „s getDelay(TimeUnit) metoda zwraca maksymalny czas wykonania danej pracy.

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); 

mają gwint wielokrotnie take() z kolejki i sprawdzić, czy każdy DelayedImpl „s Future jest zakończona przez wywołanie isDone(); Jeśli nie, anuluj zadanie.

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(); 

Główną zaletą tego podejścia jest to, że można ustawić inny maksymalny czas wykonania za zadanie i kolejki opóźnienia automatycznie powróci zadanie z najmniejszą ilość czasu wykonania pozostały.

+0

Future.get (długi limit czasu, jednostka TimeUnit), który rzuca TimeoutException na pewno to zrobi? Przypuszczam, że w haczyku na ten wyjątek nazywasz future.cancel (true) ... – JeeBee

+0

Future.get (long, TimeUnit) będzie blokować do określonego czasu dla tego * konkretnego * Future to complete. Jednak dodane przeze mnie rozwiązanie pozwala na sprawdzenie pojedynczego wątku * wszystkich * Aktywnych kalek, zamiast * blokowania * na konkretnym. Załóżmy, że przesyłam żądanie, które powinno zająć 5 minut; w moim wątku "check" wywołuję future.get (5L, TimeUnit.MINUTES). Następnie przesłana zostanie kolejna wersja z maksymalnym czasem wykonania 10 sekund. Jednak wątek nie będzie sprawdzał, czy ten drugi tryb wywoływania działa przez> 10 sekund, dopóki nie powróci poprzednie wywołanie blokujące. – Adamski

4

Adamski:

Wierzę, że realizacja opóźnionego interfejsu wymaga pewnej korekty w celu poprawnego działania. Zwracana wartość "getDelay()" powinna zwracać wartość ujemną, jeśli ilość czasu, jaki minął od instancji obiektu, przekroczyła maksymalny czas życia. Aby to osiągnąć, musisz zapamiętać czas utworzenia zadania (i prawdopodobnie zaczął). Następnie za każdym razem, gdy wywoływana jest funkcja "getDelay()", oblicz, czy przekroczono maksymalny czas życia wątku. Tak jak w:

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; 
    } 
} 
Powiązane problemy