Лучшие способы обработать максимальное время выполнения для потоков (в Java)

Что-то вроде этого не должно быть слишком плохим:

void slurp(std::string& data, const std::string& filename, bool is_binary)
{
    std::ios_base::openmode openmode = ios::ate | ios::in;
    if (is_binary)
        openmode |= ios::binary;
    ifstream file(filename.c_str(), openmode);
    data.clear();
    data.reserve(file.tellg());
    file.seekg(0, ios::beg);
    data.append(istreambuf_iterator<char>(file.rdbuf()), 
                istreambuf_iterator<char>());
}

преимущество здесь состоит в том, что мы делаем резерв сначала, таким образом, мы не должны будем выращивать строку, поскольку мы читаем вещи в. Недостаток - то, что мы делаем это символ символом. Более умная версия могла захватить целое чтение buf и затем назвать потерю значимости.

7
задан willCode4Beer 5 August 2009 в 16:48
поделиться

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;
        }
    }
}
3
ответ дан 6 December 2019 в 21:17
поделиться

Как насчет:

Отправьте свой Callable в ExecutorService и сохраните дескриптор возвращенного Future .

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

Оберните Future в реализацию Delayed , при этом метод Delayed getDelay (TimeUnit) возвращает максимальное время выполнения для

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 () из очереди и проверьте, завершены ли Future каждого DelayedImpl , выполнив вызов isDone () ; Если нет, то отмените задание.

5
ответ дан 6 December 2019 в 21:17
поделиться

Адамски:

Я считаю, что ваша реализация отложенного интерфейса требует некоторой настройки для правильной работы. Возвращаемое значение 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;
    }
}
4
ответ дан 6 December 2019 в 21:17
поделиться