8 Stimmen

Beste Methoden zur Handhabung der maximalen Ausführungszeit für Threads (in Java)

Also, ich bin neugierig. Wie handhaben Sie die Einstellung der maximalen Ausführungszeit für Threads? Wenn sie in einem Thread-Pool laufen?

Ich habe mehrere Techniken, aber ich bin nie ganz zufrieden damit. Also dachte ich mir, ich frage die Community, wie sie vorgeht.

5voto

Adamski Punkte 52945

Wie wäre es damit:

Senden Sie Ihr Callable au ExecutorService und ein Handle auf den zurückgegebenen Future .

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

Wickeln Sie die Future in einer Implementierung von Delayed wobei Delayed 's getDelay(TimeUnit) Methode gibt die maximale Ausführungszeit für die betreffende Arbeit zurück.

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

Wiederholt einen Faden haben take() aus der Warteschlange und prüfen, ob jeder DelayedImpl 's Future ist abgeschlossen durch den Aufruf von isDone() Wenn nicht, brechen Sie die Aufgabe ab.

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

Der Hauptvorteil dieses Ansatzes ist, dass Sie eine unterschiedliche maximale Ausführungszeit pro Aufgabe und die Verzögerungswarteschlange wird automatisch die Aufgabe mit der geringsten verbleibenden Ausführungszeit zurückgeben.

4voto

Jason Buberel Punkte 4706

Adamski:

Ich glaube, dass Ihre Implementierung der verzögerten Schnittstelle einige Anpassungen erfordert, damit sie richtig funktioniert. Der Rückgabewert von 'getDelay()' sollte einen negativen Wert zurückgeben, wenn die seit der Instanziierung des Objekts verstrichene Zeit die maximale Lebensdauer überschritten hat. Um dies zu erreichen, müssen Sie den Zeitpunkt speichern, zu dem die Aufgabe erstellt (und vermutlich gestartet) wurde. Dann ist bei jedem Aufruf von 'getDelay()' zu berechnen, ob die maximale Lebensdauer des Threads überschritten wurde oder nicht. Wie in:

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

3voto

Martin Blech Punkte 12445

Normalerweise rufe ich einfach regelmäßig ein Steuerobjekt aus dem threaded Code ab. Etwas wie:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X