Вот один из способов с ave
:
ave(df$a, cumsum(c(F, diff(df$a) < 0)), FUN=seq_along) - 1
[1] 0 1 2 3 0 1 2 3 4 5 6 0 1 0
Мы можем получить текущее количество, сгруппированное по diff(df$a) < 0
. Каковы позиции в векторе, которые меньше их предшественников. Мы добавим c(F, ..)
для учета первой позиции. Суммарная сумма этого вектора создает индекс для группировки. Функция ave
может выполнять функцию по этому индексу, мы используем seq_along
для текущего подсчета. Но поскольку он начинается с 1, мы вычитаем один ave(...) - 1
, чтобы начать с нуля.
Аналогичный подход с использованием dplyr
:
library(dplyr)
df %>%
group_by(cumsum(c(FALSE, diff(a) < 0))) %>%
mutate(row_number() - 1)
Используйте ExecutorService
для выполнения Callable
, проверьте методы, в которых можно указать тайм-аут. Например.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Здесь Task
, конечно, реализует Callable
.
Не напрямую; Я думаю, что самый простой способ - это выполнить join () в этом потоке с этим ограничением времени и прервать поток, если это не будет выполнено к моменту завершения соединения.
Итак,
Thread t = ...
t.join(timelimit);
if (t.isAlive()) t.interrupt();
Заметьте, я использовал прерывание вместо того, чтобы его убивать, это намного безопаснее. Я бы также рекомендовал использовать исполнителей вместо прямого управления потоками.
Почему бы не прервать ()
через определенное время? Созданный вами поток должен уметь правильно обрабатывать InterruptedException
.
См. Эту статью ( http://www.javaspecialists.eu/archive/Issue056.html ) для получения дополнительной информации о полном закрытии потоков.
См. Также структуру Executor / Future, которая предоставляет полезные методы для сбора результатов и / или завершения потоков в определенные временные рамки.
Как правило, отключение потока - плохая идея по причинам, указанным в документации API для Thread
.
Если вы твердо настроены на убийство, используйте совершенно новый процесс.
В противном случае обычным делом является опрос потока System.nanoTime
, опрос (возможно volatile
) флага, постановка в очередь «ядовитой таблетки» или что-то в этом роде.
Брайан прав, прервать его безопаснее, чем "остановить" поток.
Что делать, если поток блокирует объект в середине модификации и внезапно останавливается (что приводит к снятию блокировки)? Вы получаете странные результаты.
Не используйте destroy ()
с тех пор не выполняет никакой очистки.
Самый простой способ - использовать join ()
, например
try {
thread.join();
} catch (InterruptedException e) {//log exception...}
. Вы можете использовать ExecutorService
. Это имело бы смысл, если бы у вас было несколько потоков, работающих одновременно. Если вам нужно создавать новые потоки во время работы других потоков, вы можете объединить это с BlockingQueue
.
ThreadPoolExecutor
(реализация ExecutorService
) может принимать BlockingQueue
в качестве аргумента, и вы можете просто добавлять новые потоки в очередь. Когда вы закончите, просто завершите работу ThreadPoolExecutor
.
private BlockingQueue<Runnable> queue;
...
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000),
TimeUnit.MILLISECONDS, this.queue);
Вы можете вести подсчет всех потоков, добавленных в очередь. Когда вы думаете, что закончили (очередь, возможно, пуста?), Просто сравните это с
if (issuedThreads == pool.getCompletedTaskCount()) {
pool.shutdown();
}
. Если два совпадают, вы закончили. Другой способ завершить пул - подождать секунду в цикле:
try {
while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {//log exception...}