Есть ли стандартный хороший способ вызвать метод блокировки с тайм-аутом в Java? Я хочу уметь:
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
если это имеет смысл.
Спасибо.
java
concurrency
Jjujuma
источник
источник
Ответы:
Вы можете использовать Executor:
Если
future.get
не возвращается в течение 5 секунд, он бросаетTimeoutException
. Тайм-аут может быть настроен в секундах, минутах, миллисекундах или в любых единицах, доступных в качестве константы вTimeUnit
.См. JavaDoc для более подробной информации.
источник
BlockingMethodCallable
которого принимает параметры, которые вы хотите передать,blockingMethod()
и сохраните их как переменные-члены (возможно, как окончательные). Затем внутриcall()
передайте эти параметры вblockMethod()
.future.cancel(true)
- Метод cancel (логический) в типе Future <Object> не применим для arguments ()Вы можете заключить вызов в a
FutureTask
и использовать версию get () с тайм-аутом.См. Http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html
источник
Смотрите также гуавы в TimeLimiter , которая использует Исполнитель за кулисами.
источник
Это действительно здорово, что люди пытаются реализовать это разными способами. Но правда в том, что пути нет.
Большинство разработчиков попытаются поместить блокирующий вызов в другой поток и иметь будущее или какой-то таймер. НО в Java нет способа остановить поток извне, не говоря уже о некоторых очень конкретных случаях, таких как методы Thread.sleep () и Lock.lockInterruptibly (), которые явно обрабатывают прерывание потока.
Итак, на самом деле у вас есть только 3 общих варианта:
Поместите свой блокирующий вызов в новый поток, и если время истечет, вы просто продолжите, оставив этот поток висеть. В этом случае вы должны убедиться, что поток настроен как поток демона. Таким образом, поток не остановит ваше приложение от завершения.
Используйте неблокирующие API Java. Так, например, для сети используйте NIO2 и используйте неблокирующие методы. Для чтения из консоли используйте Scanner.hasNext () перед блокировкой и т. Д.
Если ваш блокирующий вызов - это не ввод-вывод, а ваша логика, то вы можете повторно проверить, не
Thread.isInterrupted()
был ли он прерван извне, и вызвать другой потокthread.interrupt()
в блокирующем потоке.Этот курс о параллелизме https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
действительно проходит через эти основы, если вы действительно хотите понять, как это работает в Java. На самом деле он говорит об этих конкретных ограничениях и сценариях, а также о том, как их обойти в одной из лекций.
Лично я стараюсь программировать, по возможности не используя блокирующие вызовы. Например, существуют наборы инструментов, такие как Vert.x, которые позволяют легко и эффективно выполнять операции ввода-вывода и без операций ввода-вывода асинхронно и неблокирующим образом.
Я надеюсь, что это помогает
источник
Для этого также существует решение AspectJ с библиотекой jcabi-sizes .
Он не может быть более лаконичным, но вы, конечно, должны полагаться на AspectJ и вводить его в жизненный цикл сборки.
Есть статья, объясняющая это дальше: Ограничение времени выполнения метода Java
источник
Обратите внимание, что остановка устарела, лучшая альтернатива - установить какой-нибудь изменчивый логический флаг, внутри blockingMethod () проверьте его и выйдите, например:
источник
Попробуй это. Более простое решение. Гарантирует, что если блок не будет выполнен в срок. процесс завершится и выдаст исключение.
пример :
источник
Я даю вам полный код. Вместо вызываемого мной метода вы можете использовать свой метод:
источник
Предположим,
blockingMethod
просто поспите несколько миллисекунд:Мое решение заключается в использовании
wait()
и ,synchronized
как это:Так ты можешь заменить
something.blockingMethod(input)
к
something.blockingMethod(input, 2000)
Надеюсь, поможет.
источник
Вам понадобится реализация автоматического выключателя, подобная той, которая присутствует в отказоустойчивом проекте на GitHub.
источник