texto mostrar font ejemplo java timeout multithreading timer

java - mostrar - Cómo agotar un hilo



mostrar texto en jlabel java (17)

Quiero ejecutar un hilo por un tiempo fijo. Si no se completa dentro de ese tiempo, quiero matarlo, lanzar una excepción o manejarlo de alguna manera. ¿Cómo puede hacerse esto?

Una forma de hacerlo cuando me di cuenta de este hilo es usar una Tarea de Timer dentro del método run () del Hilo.

¿Hay mejores soluciones para esto?


EDITAR: Agregar una recompensa ya que necesitaba una respuesta más clara. El código ExecutorService que se proporciona a continuación no soluciona mi problema. ¿Por qué debería dormir () después de ejecutar (algún código, no tengo control sobre este fragmento de código)? Si el código se completa y el sleep () se interrumpe, ¿cómo puede ser un timeOut?

La tarea que debe ejecutarse no está bajo mi control. Puede ser cualquier pieza de código. El problema es que este fragmento de código puede ejecutarse en un bucle infinito. No quiero que eso suceda. Entonces, solo quiero ejecutar esa tarea en un hilo separado. El subproceso principal debe esperar hasta que ese subproceso finalice y necesite conocer el estado de la tarea (es decir, si se agotó el tiempo de espera o si se produjo alguna excepción o si es un éxito). Si la tarea entra en un bucle infinito, mi hilo padre sigue esperando indefinidamente, lo que no es una situación ideal.


Ahora, me encuentro con un problema como este. Sucede decodificar la imagen. El proceso de decodificación lleva demasiado tiempo para que la pantalla se mantenga en negro. Agrego un controlador de tiempo: cuando el tiempo es demasiado largo, aparece un mensaje emergente del hilo actual. El siguiente es el diff:

ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Bitmap> future = executor.submit(new Callable<Bitmap>() { @Override public Bitmap call() throws Exception { Bitmap bitmap = decodeAndScaleBitmapFromStream(context, inputUri);// do some time consuming operation return null; } }); try { Bitmap result = future.get(1, TimeUnit.SECONDS); } catch (TimeoutException e){ future.cancel(true); } executor.shutdown(); return (bitmap!= null);


Aquí está mi clase de ayuda realmente simple de usar para run o call parte del código Java :-)

Esto se basa en la excelente answer de BalusC

package com.mycompany.util.concurrent; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Calling {@link Callable#call()} or Running {@link Runnable#run()} code * with a timeout based on {@link Future#get(long, TimeUnit))} * @author pascaldalfarra * */ public class CallableHelper { private CallableHelper() { } public static final void run(final Runnable runnable, int timeoutInSeconds) { run(runnable, null, timeoutInSeconds); } public static final void run(final Runnable runnable, Runnable timeoutCallback, int timeoutInSeconds) { call(new Callable<Void>() { @Override public Void call() throws Exception { runnable.run(); return null; } }, timeoutCallback, timeoutInSeconds); } public static final <T> T call(final Callable<T> callable, int timeoutInSeconds) { return call(callable, null, timeoutInSeconds); } public static final <T> T call(final Callable<T> callable, Runnable timeoutCallback, int timeoutInSeconds) { ExecutorService executor = Executors.newSingleThreadExecutor(); try { Future<T> future = executor.submit(callable); T result = future.get(timeoutInSeconds, TimeUnit.SECONDS); System.out.println("CallableHelper - Finished!"); return result; } catch (TimeoutException e) { System.out.println("CallableHelper - TimeoutException!"); if(timeoutCallback != null) { timeoutCallback.run(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } finally { executor.shutdownNow(); executor = null; } return null; } }


BalusC dijo:

Actualización: para aclarar un malentendido conceptual, no se requiere el sleep (). Sólo se utiliza para fines de demostración / SSCCE. Simplemente haga su tarea de larga duración allí en lugar de dormir ().

Pero si reemplazas Thread.sleep(4000); con for (int i = 0; i < 5E8; i++) {} entonces no se compila, porque el bucle vacío no lanza una InterruptedException .

Y para que el hilo sea interrumpible, debe lanzar una InterruptedException .

Esto me parece un problema serio. No puedo ver cómo adaptar esta respuesta para trabajar con una tarea general de larga duración.

Editado para agregar: Repetí esto como una nueva pregunta: [ interrumpiendo un hilo después de un tiempo fijo, ¿tiene que lanzar InterruptedException? ]


Considere usar una instancia de ExecutorService . Los invokeAll() e invokeAny() están disponibles con un parámetro de timeout .

El subproceso actual se bloqueará hasta que el método se complete (no estoy seguro de si esto es deseable) ya sea porque las tareas se completaron normalmente o se alcanzó el tiempo de espera. Puede inspeccionar los Future devueltos para determinar qué sucedió.


Creé una clase de ayuda solo para esto hace algún tiempo. Funciona genial:

import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * TimeOut class - used for stopping a thread that is taking too long * @author Peter Goransson * */ public class TimeOut { Thread interrupter; Thread target; long timeout; boolean success; boolean forceStop; CyclicBarrier barrier; /** * * @param target The Runnable target to be executed * @param timeout The time in milliseconds before target will be interrupted or stopped * @param forceStop If true, will Thread.stop() this target instead of just interrupt() */ public TimeOut(Runnable target, long timeout, boolean forceStop) { this.timeout = timeout; this.forceStop = forceStop; this.target = new Thread(target); this.interrupter = new Thread(new Interrupter()); barrier = new CyclicBarrier(2); // There will always be just 2 threads waiting on this barrier } public boolean execute() throws InterruptedException { // Start target and interrupter target.start(); interrupter.start(); // Wait for target to finish or be interrupted by interrupter target.join(); interrupter.interrupt(); // stop the interrupter try { barrier.await(); // Need to wait on this barrier to make sure status is set } catch (BrokenBarrierException e) { // Something horrible happened, assume we failed success = false; } return success; // status is set in the Interrupter inner class } private class Interrupter implements Runnable { Interrupter() {} public void run() { try { Thread.sleep(timeout); // Wait for timeout period and then kill this target if (forceStop) { target.stop(); // Need to use stop instead of interrupt since we''re trying to kill this thread } else { target.interrupt(); // Gracefully interrupt the waiting thread } System.out.println("done"); success = false; } catch (InterruptedException e) { success = true; } try { barrier.await(); // Need to wait on this barrier } catch (InterruptedException e) { // If the Child and Interrupter finish at the exact same millisecond we''ll get here // In this weird case assume it failed success = false; } catch (BrokenBarrierException e) { // Something horrible happened, assume we failed success = false; } } } }

Se llama así:

long timeout = 10000; // number of milliseconds before timeout TimeOut t = new TimeOut(new PhotoProcessor(filePath, params), timeout, true); try { boolean sucess = t.execute(); // Will return false if this times out if (!sucess) { // This thread timed out } else { // This thread ran completely and did not timeout } } catch (InterruptedException e) {}


Creo que deberías echar un vistazo a los mecanismos adecuados de manejo de concurrencia (los hilos que se ejecutan en bucles infinitos no suenan bien por sí mismos, por cierto). Asegúrese de leer un poco sobre el tema "Matar" o "Detener" Temas .

Lo que estás describiendo, suena muy parecido a una "cita", por lo que es posible que desees echar un vistazo a CyclicBarrier .

Puede haber otras construcciones (como el uso de CountDownLatch por ejemplo) que puede resolver su problema (un hilo que espera con un tiempo de espera para el pestillo, el otro debería contar el latch si ha funcionado, lo que liberaría su primer hilo después de un tiempo de espera o cuando se invoca la cuenta atrás de latch).

Generalmente recomiendo dos libros en esta área: Programación concurrente en Java y Java concurrencia en la práctica .


Creo que la respuesta depende principalmente de la tarea en sí.

  • ¿Está haciendo una tarea una y otra vez?
  • ¿Es necesario que el tiempo de espera interrumpa una tarea actualmente en ejecución inmediatamente después de que caduque?

Si la primera respuesta es sí y la segunda es no, podría ser tan simple como esto:

public class Main { private static final class TimeoutTask extends Thread { private final long _timeoutMs; private Runnable _runnable; private TimeoutTask(long timeoutMs, Runnable runnable) { _timeoutMs = timeoutMs; _runnable = runnable; } @Override public void run() { long start = System.currentTimeMillis(); while (System.currentTimeMillis() < (start + _timeoutMs)) { _runnable.run(); } System.out.println("execution took " + (System.currentTimeMillis() - start) +" ms"); } } public static void main(String[] args) throws Exception { new TimeoutTask(2000L, new Runnable() { @Override public void run() { System.out.println("doing something ..."); try { // pretend it''s taking somewhat longer than it really does Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start(); } }

Si esta no es una opción, reduzca sus requisitos o muestre un código.


De hecho, en lugar de usar ExecutorService lugar de Timer , aquí hay un SSCCE :

package com..q2275443; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class Test { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(new Task()); try { System.out.println("Started.."); System.out.println(future.get(3, TimeUnit.SECONDS)); System.out.println("Finished!"); } catch (TimeoutException e) { future.cancel(true); System.out.println("Terminated!"); } executor.shutdownNow(); } } class Task implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(4000); // Just to demo a long running task of 4 seconds. return "Ready!"; } }

Juegue un poco con el argumento del timeout en Future#get() método Future#get() , por ejemplo, auméntelo a 5 y verá que el hilo finaliza. Puede interceptar el tiempo de espera en el bloque catch (TimeoutException e) .

Actualización: para aclarar un malentendido conceptual, no se requiere el sleep() . Sólo se utiliza para fines de demostración / SSCCE. Simplemente haga su tarea de larga duración allí en lugar de sleep() . Dentro de su tarea de ejecución prolongada, debe verificar si el hilo no se interrupted siguiente manera:

while (!Thread.interrupted()) { // Do your long running task here. }


El siguiente fragmento de código iniciará una operación en un hilo separado, luego esperará hasta 10 segundos para que se complete la operación. Si la operación no se completa a tiempo, el código intentará cancelar la operación y luego continuará su camino feliz. Incluso si la operación no se puede cancelar fácilmente, el subproceso principal no esperará a que finalice el subproceso secundario.

ExecutorService executorService = getExecutorService(); Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() { public SomeClass call() { // Perform long-running task, return result. The code should check // interrupt status regularly, to facilitate cancellation. } }); try { // Real life code should define the timeout as a constant or // retrieve it from configuration SomeClass result = future.get(10, TimeUnit.SECONDS); // Do something with the result } catch (TimeoutException e) { future.cancel(true); // Perform other error handling, e.g. logging, throwing an exception }

El método getExecutorService() se puede implementar de varias maneras. Si no tiene ningún requisito en particular, simplemente puede llamar a Executors.newCachedThreadPool() para la agrupación de subprocesos sin límite superior en el número de subprocesos.


En la solución dada por BalusC , el hilo principal permanecerá bloqueado durante el tiempo de espera. Si tiene un grupo de subprocesos con más de un subproceso, necesitará la misma cantidad de subprocesos adicionales que utilizarán Future.get (unidad de TimeUnit de tiempo de espera largo) para esperar y cerrar el hilo si supera el período de tiempo de espera.

Una solución genérica para este problema es crear un decorador ThreadPoolExecutor que pueda agregar la funcionalidad de tiempo de espera. Esta clase de Decorator debe crear tantos hilos como ThreadPoolExecutor tiene, y todos estos hilos deben usarse solo para esperar y cerrar el ThreadPoolExecutor.

La clase genérica se debe implementar como a continuación:

import java.util.List; import java.util.concurrent.*; public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor { private final ThreadPoolExecutor commandThreadpool; private final long timeout; private final TimeUnit unit; public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool, long timeout, TimeUnit unit ){ super( threadpool.getCorePoolSize(), threadpool.getMaximumPoolSize(), threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS, threadpool.getQueue()); this.commandThreadpool = threadpool; this.timeout=timeout; this.unit=unit; } @Override public void execute(Runnable command) { super.execute(() -> { Future<?> future = commandThreadpool.submit(command); try { future.get(timeout, unit); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException | TimeoutException e) { throw new RejectedExecutionException(e); } finally { future.cancel(true); } }); } @Override public void setCorePoolSize(int corePoolSize) { super.setCorePoolSize(corePoolSize); commandThreadpool.setCorePoolSize(corePoolSize); } @Override public void setThreadFactory(ThreadFactory threadFactory) { super.setThreadFactory(threadFactory); commandThreadpool.setThreadFactory(threadFactory); } @Override public void setMaximumPoolSize(int maximumPoolSize) { super.setMaximumPoolSize(maximumPoolSize); commandThreadpool.setMaximumPoolSize(maximumPoolSize); } @Override public void setKeepAliveTime(long time, TimeUnit unit) { super.setKeepAliveTime(time, unit); commandThreadpool.setKeepAliveTime(time, unit); } @Override public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { super.setRejectedExecutionHandler(handler); commandThreadpool.setRejectedExecutionHandler(handler); } @Override public List<Runnable> shutdownNow() { List<Runnable> taskList = super.shutdownNow(); taskList.addAll(commandThreadpool.shutdownNow()); return taskList; } @Override public void shutdown() { super.shutdown(); commandThreadpool.shutdown(); } }

El decorador anterior se puede utilizar de la siguiente manera:

import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args){ long timeout = 2000; ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true)); threadPool = new TimeoutThreadPoolDecorator( threadPool , timeout, TimeUnit.MILLISECONDS); threadPool.execute(command(1000)); threadPool.execute(command(1500)); threadPool.execute(command(2100)); threadPool.execute(command(2001)); while(threadPool.getActiveCount()>0); threadPool.shutdown(); } private static Runnable command(int i) { return () -> { System.out.println("Running Thread:"+Thread.currentThread().getName()); System.out.println("Starting command with sleep:"+i); try { Thread.sleep(i); } catch (InterruptedException e) { System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!"); return; } System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i); }; } }


Estaba buscando un ExecutorService que puede interrumpir todos los Runnables ejecutados por el tiempo de espera, pero no encontró ninguno. Después de unas horas creé uno como el siguiente. Esta clase se puede modificar para mejorar la robustez.

public class TimedExecutorService extends ThreadPoolExecutor { long timeout; public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) { super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(numThreads + 1)); this.timeout = unit.toMillis(timeout); } @Override protected void beforeExecute(Thread thread, Runnable runnable) { Thread interruptionThread = new Thread(new Runnable() { @Override public void run() { try { // Wait until timeout and interrupt this thread Thread.sleep(timeout); System.out.println("The runnable times out."); thread.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }); interruptionThread.start(); } }

Uso:

public static void main(String[] args) { Runnable abcdRunnable = new Runnable() { @Override public void run() { System.out.println("abcdRunnable started"); try { Thread.sleep(20000); } catch (InterruptedException e) { // logger.info("The runnable times out."); } System.out.println("abcdRunnable ended"); } }; Runnable xyzwRunnable = new Runnable() { @Override public void run() { System.out.println("xyzwRunnable started"); try { Thread.sleep(20000); } catch (InterruptedException e) { // logger.info("The runnable times out."); } System.out.println("xyzwRunnable ended"); } }; int numThreads = 2, timeout = 5; ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS); timedExecutor.execute(abcdRunnable); timedExecutor.execute(xyzwRunnable); timedExecutor.shutdown(); }


Gran respuesta de BalusC''s:

pero solo para agregar que el tiempo de espera en sí no interrumpe el hilo en sí. incluso si está marcando con while (! Thread.interrupted ()) en su tarea. Si desea asegurarse de que el subproceso está detenido, también debe asegurarse de que se invoca future.cancel () cuando se retiene la excepción de tiempo de espera.

package com..q2275443; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class Test { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(new Task()); try { System.out.println("Started.."); System.out.println(future.get(3, TimeUnit.SECONDS)); System.out.println("Finished!"); } catch (TimeoutException e) { //Without the below cancel the thread will continue to live // even though the timeout exception thrown. future.cancel(); System.out.println("Terminated!"); } executor.shutdownNow(); } } class Task implements Callable<String> { @Override public String call() throws Exception { while(!Thread.currentThread.isInterrupted()){ System.out.println("Im still running baby!!"); } } }


No hay una forma 100% confiable de hacer esto para cualquier tarea anterior. La tarea debe escribirse con esta habilidad en mente.

Las bibliotecas principales de Java como ExecutorService cancelan las tareas asíncronas con llamadas de interrupt() en el subproceso de trabajo. Entonces, por ejemplo, si la tarea contiene algún tipo de bucle, debe verificar su estado de interrupción en cada iteración. Si la tarea es realizar operaciones de E / S, también deberían ser interrumpibles, y configurarlas puede ser complicado. En cualquier caso, tenga en cuenta que el código debe verificar activamente las interrupciones; establecer una interrupción no necesariamente hace nada.

Por supuesto, si su tarea es un bucle simple, puede verificar la hora actual en cada iteración y darse por vencido cuando haya transcurrido un tiempo de espera específico. No se necesita un hilo de trabajo en ese caso.


Suponiendo que el código de hilo está fuera de su control:

De la documentation Java mencionada anteriormente:

¿Qué pasa si un hilo no responde a Thread.interrupt?

En algunos casos, puede utilizar trucos específicos de la aplicación. Por ejemplo, si un hilo está esperando en un socket conocido, puede cerrar el socket para hacer que el hilo regrese inmediatamente. Desafortunadamente, realmente no hay ninguna técnica que funcione en general. Se debe tener en cuenta que en todas las situaciones en las que un hilo en espera no responde a Thread.interrupt, tampoco respondería a Thread.stop. Tales casos incluyen ataques deliberados de denegación de servicio y operaciones de E / S para las cuales thread.stop y thread.interrupt no funcionan correctamente.

Línea de fondo:

Asegúrese de que todos los subprocesos puedan ser interrumpidos, o de lo contrario necesita un conocimiento específico del subproceso, como tener una bandera que establecer. Tal vez pueda requerir que se le asigne la tarea junto con el código necesario para detenerla: defina una interfaz con un método stop() . También puede avisar cuando no pudo detener una tarea.


Te publico un fragmento de código que muestra cómo resolver el problema. Como ejemplo estoy leyendo un archivo. Podría usar este método para otra operación, pero necesita implementar el método kill () para que la operación principal se interrumpa.

Espero eso ayude

import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * Main class * * @author el * */ public class Main { /** * Thread which perform the task which should be timed out. * * @author el * */ public static class MainThread extends Thread { /** * For example reading a file. File to read. */ final private File fileToRead; /** * InputStream from the file. */ final private InputStream myInputStream; /** * Thread for timeout. */ final private TimeOutThread timeOutThread; /** * true if the thread has not ended. */ boolean isRunning = true; /** * true if all tasks where done. */ boolean everythingDone = false; /** * if every thing could not be done, an {@link Exception} may have * Happens. */ Throwable endedWithException = null; /** * Constructor. * * @param file * @throws FileNotFoundException */ MainThread(File file) throws FileNotFoundException { setDaemon(false); fileToRead = file; // open the file stream. myInputStream = new FileInputStream(fileToRead); // Instantiate the timeout thread. timeOutThread = new TimeOutThread(10000, this); } /** * Used by the {@link TimeOutThread}. */ public void kill() { if (isRunning) { isRunning = false; if (myInputStream != null) { try { // close the stream, it may be the problem. myInputStream.close(); } catch (IOException e) { // Not interesting System.out.println(e.toString()); } } synchronized (this) { notify(); } } } /** * The task which should be timed out. */ @Override public void run() { timeOutThread.start(); int bytes = 0; try { // do something while (myInputStream.read() >= 0) { // may block the thread. myInputStream.read(); bytes++; // simulate a slow stream. synchronized (this) { wait(10); } } everythingDone = true; } catch (IOException e) { endedWithException = e; } catch (InterruptedException e) { endedWithException = e; } finally { timeOutThread.kill(); System.out.println("-->read " + bytes + " bytes."); isRunning = false; synchronized (this) { notifyAll(); } } } } /** * Timeout Thread. Kill the main task if necessary. * * @author el * */ public static class TimeOutThread extends Thread { final long timeout; final MainThread controlledObj; TimeOutThread(long timeout, MainThread controlledObj) { setDaemon(true); this.timeout = timeout; this.controlledObj = controlledObj; } boolean isRunning = true; /** * If we done need the {@link TimeOutThread} thread, we may kill it. */ public void kill() { isRunning = false; synchronized (this) { notify(); } } /** * */ @Override public void run() { long deltaT = 0l; try { long start = System.currentTimeMillis(); while (isRunning && deltaT < timeout) { synchronized (this) { wait(Math.max(100, timeout - deltaT)); } deltaT = System.currentTimeMillis() - start; } } catch (InterruptedException e) { // If the thread is interrupted, // you may not want to kill the main thread, // but probably yes. } finally { isRunning = false; } controlledObj.kill(); } } /** * Start the main task and wait for the end. * * @param args * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException { long start = System.currentTimeMillis(); MainThread main = new MainThread(new File(args[0])); main.start(); try { while (main.isRunning) { synchronized (main) { main.wait(1000); } } long stop = System.currentTimeMillis(); if (main.everythingDone) System.out.println("all done in " + (stop - start) + " ms."); else { System.out.println("could not do everything in " + (stop - start) + " ms."); if (main.endedWithException != null) main.endedWithException.printStackTrace(); } } catch (InterruptedException e) { System.out.println("You''ve killed me!"); } } }

Saludos


Una cosa que no he visto mencionada es que matar hilos es generalmente una mala idea. Existen técnicas para hacer que los métodos de subprocesos sean fácilmente abortibles , pero eso es diferente a solo matar un subproceso después de un tiempo de espera.

El riesgo con lo que está sugiriendo es que probablemente no sepa en qué estado estará el hilo cuando lo mate, por lo que corre el riesgo de introducir inestabilidad. Una mejor solución es asegurarse de que su código encriptado no se cuelgue solo o responderá bien a una solicitud de cancelación.


Yo tuve el mismo problema. Así que se me ocurrió una solución simple como esta.

public class TimeoutBlock { private final long timeoutMilliSeconds; private long timeoutInteval=100; public TimeoutBlock(long timeoutMilliSeconds){ this.timeoutMilliSeconds=timeoutMilliSeconds; } public void addBlock(Runnable runnable) throws Throwable{ long collectIntervals=0; Thread timeoutWorker=new Thread(runnable); timeoutWorker.start(); do{ if(collectIntervals>=this.timeoutMilliSeconds){ timeoutWorker.stop(); throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated."); } collectIntervals+=timeoutInteval; Thread.sleep(timeoutInteval); }while(timeoutWorker.isAlive()); System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds."); } /** * @return the timeoutInteval */ public long getTimeoutInteval() { return timeoutInteval; } /** * @param timeoutInteval the timeoutInteval to set */ public void setTimeoutInteval(long timeoutInteval) { this.timeoutInteval = timeoutInteval; } }

Garantiza que si el bloque no se ejecutó dentro del límite de tiempo. El proceso terminará y lanza una excepción.

ejemplo:

try { TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds Runnable block=new Runnable() { @Override public void run() { //TO DO write block of code } }; timeoutBlock.addBlock(block);// execute the runnable block } catch (Throwable e) { //catch the exception here . Which is block didn''t execute within the time limit }