Como parar / matar o Java Thread de longa duração em tempo de execução? expirado -> cancelado -> estados interrompidos
Publicados: 2021-07-17Você já se perguntou como matar threads Java de longa duração? Você tem alguma das perguntas abaixo?
- Matar/Parar um thread após certo período de tempo
- Matando thread após algum limite de tempo especificado em Java
- Como matar um thread Java
- Como parar um thread em Java com um exemplo
- como parar o thread no exemplo de código java
- como parar um thread em java sem usar o método stop
Se você tiver alguma das perguntas abaixo, então você está no lugar certo. Hoje vamos ver um exemplo simples que demonstra maneiras Java8 de matar threads de longa duração.
O que é uma lógica:
- Criar classe CrunchifyJavaTaskTimeout.java
- Crie o executor Java Thread com apenas 1 tamanho de threadpool.
- Crie 4 tarefas futuras de um objeto
CrunchifyRunner
com tempo limite de 3 segundos - CrunchifyRunner.java é uma classe simples que implementa o método
call()
- Introduz
20 seconds
atraso sefutureTask = 4
- Introduz
- Uma vez que o futuro atinge
3 seconds
, ele cria uma exceção de tempo limite se o encadeamento ainda estiver em execução- Uma vez que o tempo limite expirou, precisamos cancelar a tarefa usando crunchifyFuture.
cancel( true )
; - Uma vez que futureTask é cancelado, ele acionará
InterruptedException
(lançado quando um encadeamento está esperando, dormindo ou ocupado de outra forma, e o encadeamento é interrompido, antes ou durante a atividade. Ocasionalmente, um método pode querer testar se o encadeamento atual foi interrompido, e em caso afirmativo, para lançar imediatamente essa exceção.)
- Uma vez que o tempo limite expirou, precisamos cancelar a tarefa usando crunchifyFuture.
Vamos começar:
Etapa 1 Criar a classe CrunchifyRunner.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package crunchify . java . tutorials ; import java . text . SimpleDateFormat ; import java . util . Date ; import java . util . concurrent . Callable ; /** * @author Crunchify.com * Version: 1.0.1 * */ public class CrunchifyRunner implements Callable < Boolean > { private int workerNumber ; public int getNumber ( ) { return workerNumber ; } public void setNumber ( int workerNumber ) { this . workerNumber = workerNumber ; } public CrunchifyRunner ( int workerNumber ) { this . workerNumber = workerNumber ; setNumber ( workerNumber ) ; } SimpleDateFormat crunchifyFormatter = new SimpleDateFormat ( "dd-MMMMM-yyyy hh:mm:ss" ) ; public Boolean call ( ) throws InterruptedException { try { if ( workerNumber == 4 ) { // Sleep for 20 Seconds to generate long running thread. Thread . sleep ( 20000 ) ; } else { Thread . sleep ( 50 ) ; } } catch ( InterruptedException ie ) { log ( "\n" + crunchifyFormatter . format ( new Date ( ) ) + " crunchifyWorker task " + workerNumber + " interrupted." ) ; log ( "\n=======> Basically once thread is timed out, it should be cancelled and interrupted. (timedout ==> cancelled ==> interrupted)" ) ; } // Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a // method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception. return true ; } public void log ( String info ) { System . out . println ( info ) ; } } |
Etapa 2 Crie a classe CrunchifyJavaTaskTimeout.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
package crunchify . java . tutorials ; import java . text . SimpleDateFormat ; import java . util . ArrayList ; import java . util . Collection ; import java . util . Date ; import java . util . List ; import java . util . concurrent . Callable ; import java . util . concurrent . CompletionService ; import java . util . concurrent . ExecutionException ; import java . util . concurrent . ExecutorCompletionService ; import java . util . concurrent . Executors ; import java . util . concurrent . Future ; import java . util . concurrent . TimeUnit ; /** * @author Crunchify.com * Version: 1.0.2 * */ public class CrunchifyJavaTaskTimeout { @ SuppressWarnings ( { "rawtypes" , "unchecked" } ) public static void main ( final String [ ] args ) { // Creates an ExecutorCompletionService using the supplied executor for base task execution and a LinkedBlockingQueue as a completion queue. CompletionService < Boolean > crunchifyService = new ExecutorCompletionService < Boolean > ( Executors . newFixedThreadPool ( 1 ) ) ; Collection < CrunchifyRunner > crunchifyThreads = new ArrayList < CrunchifyRunner > ( 50 ) ; crunchifyThreads . add ( new CrunchifyRunner ( 1 ) ) ; crunchifyThreads . add ( new CrunchifyRunner ( 2 ) ) ; crunchifyThreads . add ( new CrunchifyRunner ( 3 ) ) ; crunchifyThreads . add ( new CrunchifyRunner ( 4 ) ) ; SimpleDateFormat crunchifyFormatter = new SimpleDateFormat ( "dd-MMMMM-yyyy hh:mm:ss" ) ; List < Future < Boolean > > crunchifyFutures = new ArrayList < Future < Boolean > > ( crunchifyThreads . size ( ) ) ; try { // Let's first add all tasks to future for ( Callable crunchifyTask : crunchifyThreads ) { crunchifyFutures . add ( crunchifyService . submit ( crunchifyTask ) ) ; } for ( int count = 1 ; count < = crunchifyFutures . size ( ) ; count ++ ) { // Let's put Future timeout to 3 Seconds Future < Boolean > crunchifyResult = crunchifyService . poll ( 3000 , TimeUnit . MILLISECONDS ) ; if ( crunchifyResult == null ) { log ( crunchifyFormatter . format ( new Date ( ) ) + "\n ==> crunchifyWorker task " + count + " timedout." ) ; // So lets cancel the first futures we find that haven't completed for ( Future crunchifyFuture : crunchifyFutures ) { if ( crunchifyFuture . isDone ( ) ) { continue ; } else { crunchifyFuture . cancel ( true ) ; log ( " ==> crunchifyWorker task " + count + " cancelled." ) ; break ; } } continue ; } else { try { if ( crunchifyResult . isDone ( ) && !crunchifyResult.isCancelled() && crunchifyResult.get()) { log(crunchifyFormatter.format(new Date()) + " ==> crunchifyWorker task " + count + " completed."); } else { log ( crunchifyFormatter . format ( new Date ( ) ) + " ==> crunchifyWorker task failed" ) ; } } catch ( ExecutionException exception ) { log ( exception . getMessage ( ) ) ; } } } } catch ( InterruptedException exception ) { // Log exception message log ( exception . getMessage ( ) ) ; } finally { // Cancel by interrupting any existing tasks currently running in Executor Service for ( Future < Boolean > future : crunchifyFutures ) { future . cancel ( true ) ; } } log ( "\n=======> All tasks completed. Now long running thread 4 should be interrupted immediately after this." ) ; System . exit ( 0 ) ; } private static void log ( String string ) { System . out . println ( string ) ; } } |

Etapa 3
Clique com o botão direito do mouse em CrunchifyJavaTaskTimeout.java e execute-o como um aplicativo Java.
Você verá abaixo o resultado no console do Eclipse.
1 2 3 4 5 6 7 8 9 10 11 12 |
27 - November - 2018 10 : 32 : 29 == > crunchifyWorker task 1 completed . 27 - November - 2018 10 : 32 : 29 == > crunchifyWorker task 2 completed . 27 - November - 2018 10 : 32 : 29 == > crunchifyWorker task 3 completed . 27 - November - 2018 10 : 32 : 32 == > crunchifyWorker task 4 timedout . == > crunchifyWorker task 4 cancelled . ======= > All tasks completed . Now long running thread 4 should be interrupted immediately after this . 27 - November - 2018 10 : 32 : 32 crunchifyWorker task 4 interrupted . ======= > Basically once thread is timed out , it should be cancelled and interrupted . ( timedout == > cancelled == > interrupted ) |
Deixe-me saber se você tem alguma dúvida sobre este tópico.