ScheduledExecutorService — задача перестает выполняться

private ScheduledExecutorService pool = new ScheduledThreadPoolExecutor(20);

я выполняю задание

public void run() {
    if (queue.isEmpty()) return;

    ArrayDeque<Profile> current = new ArrayDeque<Profile>();
    this.queue.drainTo(current, 20);

    MySQLStatement statement = this.wrapper.prepare();

    while (!current.isEmpty()) {
        if (statement.isClosed()) return;

        Profile profile = current.poll();
        statement.addBatch(profile.getId().toString(), ProfileBuilder.toJson(profile));
    }

    statement.executeBatchAsync();
}

с помощью ScheduledExecutorService

pool.scheduleAtFixedRate(new VerboseRunnable(runnable = new MySQLRunnable(this)), 250, 50, TimeUnit.MILLISECONDS);  

MySQLRunnable перестает работать после некоторых запусков с полной очередью, но работает более или менее бесконечно, когда очередь пуста.
Сначала я подумал, что остановки могут быть из-за молча пойманного исключения, поэтому я добавил VerboseRunnable

public void run() {
    try {
        runnable.run();
    } catch (Throwable e) {
        System.err.println("Error in runnable!");
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

Но все равно перестает запускаться. Также ScheduledFuture сообщает мне, что задача не выполнена и не отменена.

Любая помощь будет приятно.


person Jofkos    schedule 26.08.2015    source источник
comment
Вы закрываете свои заявления и связи? Также было бы неплохо показать, что делает this.wrapper.prepare()?   -  person dcsohl    schedule 26.08.2015
comment
@dcsohl Закрытие операторов - хорошая идея, скорее всего, это решение. Но почему задача перестает работать, если я их не закрываю?   -  person Jofkos    schedule 26.08.2015
comment
Вот почему я спросил, что сделал this.wrapper.prepare()... потому что я не уверен на 100%. Насколько мне известно, я предполагаю, что вы извлекаете соединения из пула соединений... открытый оператор блокирует это соединение, и поэтому в определенный момент, когда вы запрашиваете новое соединение, оно просто зависает... поведение по умолчанию заключается в блокировке до тех пор, пока соединение не будет доступно (что обычно непродолжительно, если нет утечки).   -  person dcsohl    schedule 26.08.2015
comment
@dcsohl Да, верно, я вытаскиваю соединения из пула, я должен был упомянуть об этом в первом посте. Итак, вы говорите, что пул перестает раздавать соединения и просто зависает в момент, когда я пытаюсь его получить? Однако теперь я закрываю операторы и соединения, что делает это до сих пор, пока он не перестал работать.   -  person Jofkos    schedule 26.08.2015
comment
Я думаю, вы пропустили несколько слов; Я не уверен, что вы спрашиваете. Это работает? Но да, в основном, если пул настроен на 20 подключений, и в нем открыто 20 подключений, 21-й запрос обычно (в зависимости от конкретной реализации) блокируется и ждет освобождения одного из других подключений. Я считаю, что вы видели, что ваши задачи блокируются на неопределенный срок, потому что ни одно соединение не было освобождено.   -  person dcsohl    schedule 26.08.2015
comment
Да, это работает! Спасибо.   -  person Jofkos    schedule 27.08.2015


Ответы (1)


Вы всегда должны быть осторожны, закрывая ресурсы по мере их использования, особенно ресурсы ввода-вывода, такие как соединения, операторы и наборы результатов. В среде с пулом вы можете очень легко закончить тем, что пул соединений истощится, и последующие задачи в конечном итоге будут заблокированы, ожидая соединения, которое может никогда не быть доступным (если вам повезет, в зависимости от реализации и т. д., возможно, соединения начнутся закрываются через несколько минут... или дольше).

person dcsohl    schedule 27.08.2015
comment
Как упоминалось выше, это решило мою проблему. Спасибо! - person Jofkos; 28.08.2015
comment
Да - просто хотел сделать это официальным ответом. - person dcsohl; 28.08.2015