para que sirve settitle en java
Matar el hilo después de un límite de tiempo especificado en Java (8)
¿Hay alguna forma de matar un hilo secundario después de un límite de tiempo especificado en Java? Editar: También este hilo en particular puede ser bloqueado en el peor de los casos (el hilo se usa para esperar una modificación del archivo y bloquea hasta que ocurra este evento), entonces ¿no estoy seguro de que la interrupción () tendrá éxito?
¿Por qué no lo interrupt()
después de un tiempo en particular? El hilo generado tendrá que ser capaz de manejar una InterruptedException
correctamente.
Consulte este artículo ( http://www.javaspecialists.eu/archive/Issue056.html ) para obtener más información sobre el cierre limpio de los hilos.
Consulte también el marco Executor / Future, que proporciona métodos útiles para recopilar resultados y / o terminar hilos dentro de límites de tiempo específicos.
Brian tiene razón, interrumpirlo es más seguro que "detener" el hilo.
¿Qué ocurre si el hilo se bloquea en un objeto a mitad de la modificación y de repente se detiene (lo que hace que se suelte el bloqueo)? Obtienes resultados extraños.
La eliminación de un hilo generalmente es una mala idea por razones relacionadas con los documentos API para Thread
.
Si estás decidido a matar, utiliza un proceso completamente nuevo.
De lo contrario, lo habitual es tener el hilo de encuesta System.nanoTime
, sondear una bandera (posible volatile
), System.nanoTime
cola una "píldora de veneno" o algo de esa naturaleza.
No directamente; Creo que la manera más simple es unir () en ese hilo con ese límite de tiempo, e interrumpir el hilo si no está hecho para el momento en que terminó el enlace.
Asi que,
Thread t = ...
t.join(timelimit);
if (t.isAlive) t.interrupt();
Observe que usé la interrupción en lugar de matarla, es mucho más seguro. También recomendaría utilizar ejecutores en lugar de manipular directamente los hilos.
No use destroy()
ya que no realiza ninguna limpieza.
La forma más directa es usar join()
, como
try {
thread.join();
} catch (InterruptedException e) {//log exception...}
Puede usar un ExecutorService
. Eso tendría mucho sentido si tienes varios hilos ejecutándose simultáneamente. Si necesita generar nuevos subprocesos mientras se están ejecutando otros subprocesos, puede combinar esto con un BlockingQueue
.
Un ThreadPoolExecutor
(un ExecutorService
-implementation) puede tomar un BlockingQueue
como argumento, y simplemente puede agregar nuevos hilos a la cola. Cuando termines, simplemente finalizas el ThreadPoolExecutor
.
private BlockingQueue<Runnable> queue;
...
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000),
TimeUnit.MILLISECONDS, this.queue);
Puede mantener un conteo de todos los hilos agregados a la cola. Cuando piensas que terminaste (¿la cola está vacía, quizás?) Simplemente compara esto con
if (issuedThreads == pool.getCompletedTaskCount()) {
pool.shutdown();
}
Si los dos coinciden, ya terminaste. Otra forma de finalizar el grupo es esperar un segundo en un bucle:
try {
while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {//log exception...}
Puedes usar AOP y una anotación @Timeable
para tu método desde jcabi-aspects (soy desarrollador):
@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
// do something time consuming
}
Cuando se alcanza el límite de tiempo, se activará interrupted()
indicador de interrupted()
thread) de la interrupted()
thread) y será su trabajo manejar esta situación correctamente y detener la ejecución. Normalmente lo hace Thread.sleep(..)
.
Se introdujeron algunos cambios útiles como parte del JEP 266 en CompletableFuture
desde Java 9. Usando el método orTimeout , por ahora, es posible escribirlo como sigue:
CompletableFuture.runAsync(thread::run)
.orTimeout(30, TimeUnit.SECONDS)
.exceptionally(throwable -> {
log.error("An error occurred", throwable);
return null;
});
En Java 8, desafortunadamente, debería usar algún código adicional. Aquí hay un ejemplo de uso de patrones de delegación con la ayuda de Lombok :
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.TimeoutException;
import static lombok.AccessLevel.PRIVATE;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
@AllArgsConstructor(access = PRIVATE)
public class TimeoutableCompletableFuture<T> extends CompletableFuture<T> {
public static TimeoutableCompletableFuture<Void> runAsync(
Runnable runnable) {
return new TimeoutableCompletableFuture<>(
CompletableFuture.runAsync(runnable));
}
@Delegate
private final CompletableFuture<T> baseFuture;
public TimeoutableCompletableFuture<T> orTimeout(Duration duration) {
final CompletableFuture<T> otherFuture = new CompletableFuture<>();
Executors.newScheduledThreadPool(
1,
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("timeoutable-%d")
.build())
.schedule(() -> {
TimeoutException ex = new TimeoutException(
"Timeout after " + duration);
return otherFuture.completeExceptionally(ex);
}, duration.toMillis(), MILLISECONDS);
return new TimeoutableCompletableFuture<>(
baseFuture.applyToEither(otherFuture, a -> a));
}
}
Por supuesto, el código anterior fácilmente podría reescribirse como solo un método de fábrica estático:
public static CompletableFuture<Void> runAsyncOrTimeout(
Runnable runnable, long timeout, TimeUnit unit) {
CompletableFuture<Void> other = new CompletableFuture<>();
Executors.newScheduledThreadPool(
1,
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("timeoutafter-%d")
.build())
.schedule(() -> {
TimeoutException ex = new TimeoutException(
"Timeout after " + timeout);
return other.completeExceptionally(ex);
}, timeout, unit);
return CompletableFuture.runAsync(runnable).applyToEither(other, a -> a);
}
Haga uso de ExecutorService
para ejecutar Runnable
, Runnable
los métodos en los que puede especificar el tiempo de espera. P.ej
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Aquí la Task
del curso implementa Runnable
.