Existe uma maneira legal padrão de chamar um método de bloqueio com um tempo limite em Java? Eu quero ser capaz de fazer:
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
se isso faz sentido.
Obrigado.
java
concurrency
Jjujuma
fonte
fonte
Respostas:
Você poderia usar um Executor:
Se
future.get
não retornar em 5 segundos, ele gerará umTimeoutException
. O tempo limite pode ser configurado em segundos, minutos, milissegundos ou qualquer unidade disponível como uma constante emTimeUnit
.Veja o JavaDoc para mais detalhes.
fonte
BlockingMethodCallable
cujo construtor aceita os parâmetros que você deseja passarblockingMethod()
e armazene-os como variáveis de membro (provavelmente como finais). Em seguida,call()
passe esses parâmetros para oblockMethod()
.future.cancel(true)
- O método cancel (boolean) no tipo Future <Object> não é aplicável para os argumentos ()Você poderia envolver a chamada em a
FutureTask
e usar a versão de tempo limite de get ().Consulte http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html
fonte
Veja também TimeLimiter da Guava, que usa um Executor nos bastidores.
fonte
Também existe uma solução AspectJ para isso com a biblioteca de aspectos jcabi .
Não pode ser mais sucinto, mas você tem que depender do AspectJ e introduzi-lo em seu ciclo de vida de construção, é claro.
Há um artigo que explica isso melhor: Limite o tempo de execução do método Java
fonte
É muito bom que as pessoas tentem implementar isso de tantas maneiras. Mas a verdade é que NÃO há como.
A maioria dos desenvolvedores tentaria colocar a chamada de bloqueio em um thread diferente e teria um futuro ou algum temporizador. MAS não há como em Java parar um thread externamente, muito menos alguns casos muito específicos como os métodos Thread.sleep () e Lock.lockInterruptibly () que tratam explicitamente da interrupção do thread.
Então, na verdade, você tem apenas 3 opções genéricas:
Coloque sua chamada de bloqueio em um novo tópico e, se o tempo expirar, siga em frente, deixando o tópico suspenso. Nesse caso, você deve certificar-se de que o thread está definido como um thread do Daemon. Dessa forma, o thread não interromperá o encerramento do seu aplicativo.
Use APIs Java sem bloqueio. Portanto, para rede, por exemplo, use NIO2 e use os métodos sem bloqueio. Para ler a partir do console, use Scanner.hasNext () antes de bloquear etc.
Se sua chamada de bloqueio não for um IO, mas sua lógica, você pode verificar repetidamente para
Thread.isInterrupted()
verificar se foi interrompido externamente e ter outra chamada de threadthread.interrupt()
no thread de bloqueioEste curso sobre simultaneidade https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
realmente percorre esses fundamentos se você realmente deseja entender como funciona em Java. Na verdade, fala sobre essas limitações e cenários específicos e como abordá-los em uma das palestras.
Eu pessoalmente tento programar sem usar o máximo possível de chamadas de bloqueio. Existem kits de ferramentas como o Vert.x, por exemplo, que tornam realmente fácil e eficiente fazer IO e nenhuma operação IO de forma assíncrona e sem bloqueios.
Espero que ajude
fonte
Observe que a parada está obsoleta, a melhor alternativa é definir algum sinalizador booleano volátil, dentro de BlockMethod (), verifique e saia, assim:
fonte
Experimente isso. Solução mais simples. Garante que se o bloco não for executado dentro do limite de tempo. o processo será encerrado e lançará uma exceção.
exemplo:
fonte
Estou dando aqui o código completo. No lugar do método que estou chamando, você pode usar seu método:
fonte
Suponha que
blockingMethod
apenas durma por alguns milis:Minha solução é usar
wait()
esynchronized
assim:Então você pode substituir
something.blockingMethod(input)
para
something.blockingMethod(input, 2000)
Espero que ajude.
fonte
Você precisa de uma implementação de disjuntor como a presente no projeto à prova de falhas no GitHub.
fonte