¿Cómo detener/matar un subproceso Java de ejecución prolongada en tiempo de ejecución? agotado -> cancelado -> estados interrumpidos
Publicado: 2021-07-17¿Alguna vez te has preguntado cómo matar un hilo de Java de larga duración? ¿Tiene alguna de las siguientes preguntas?
- Matar/Detener un hilo después de cierto período de tiempo
- Matar hilo después de un límite de tiempo especificado en Java
- Cómo matar un hilo de Java
- Cómo detener un hilo en Java con un ejemplo
- cómo detener el hilo en el ejemplo de código Java
- cómo detener un hilo en java sin usar el método de parada
Si tiene alguna de las siguientes preguntas, entonces está en el lugar correcto. Hoy repasaremos un ejemplo simple que demuestra las formas de Java8 para eliminar hilos de ejecución prolongada.
Que es una logica:
- Crear clase CrunchifyJavaTaskTimeout.java
- Cree un ejecutor de subprocesos Java con solo 1 tamaño de grupo de subprocesos.
- Cree 4 tareas futuras de un objeto
CrunchifyRunner
con un tiempo de espera de 3 segundos - CrunchifyRunner.java es una clase simple que implementa el método
call()
- Introduce
20 seconds
retraso sifutureTask = 4
- Introduce
- Una vez que el futuro llega a
3 seconds
, crea una excepción de tiempo de espera si el hilo aún se está ejecutando- Una vez que se agote el tiempo de espera, debemos cancelar la tarea usando crunchifyFuture.
cancel( true )
; - Una vez que se cancela futureTask, activará
InterruptedException
(se lanza cuando un subproceso está esperando, durmiendo u ocupado de otra manera, y el subproceso se interrumpe, ya sea antes o durante la actividad. Ocasionalmente, un método puede desear probar si el subproceso actual se ha interrumpido, y si es así, lanzar inmediatamente esta excepción).
- Una vez que se agote el tiempo de espera, debemos cancelar la tarea usando crunchifyFuture.
Empecemos:
Paso-1 Crear clase 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 ) ; } } |
Paso-2 Crear clase 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 ) ; } } |

Paso 3
Haga clic derecho en CrunchifyJavaTaskTimeout.java y ejecútelo como una aplicación Java.
Verá el siguiente resultado en la consola de 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 ) |
Déjame saber si tienes alguna pregunta sobre este tema.