java - tiempo - Cómo detener una tarea en ScheduledThreadPoolExecutor una vez que creo que se ha completado
timertask android ejemplo (3)
Tengo un ScheduledThreadPoolExecutor con el que programo una tarea para que se ejecute a una tasa fija. Quiero que la tarea se ejecute con un retraso específico por un máximo de, por ejemplo, 10 veces hasta que "tenga éxito". Después de eso, no quiero que la tarea se vuelva a intentar. Básicamente, tendré que dejar de ejecutar la tarea programada cuando quiero que se detenga, pero sin apagar el ScheduledThreadPoolExecutor. ¿Alguna idea de cómo haría eso?
Aquí hay un pseudocódigo.
public class ScheduledThreadPoolExecutorTest
{
public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no multiple instances, just one to serve all requests
class MyTask implements Runnable
{
private int MAX_ATTEMPTS = 10;
public void run()
{
if(++attempt <= MAX_ATTEMPTS)
{
doX();
if(doXSucceeded)
{
//stop retrying the task anymore
}
}
else
{
//couldn''t succeed in MAX attempts, don''t bother retrying anymore!
}
}
}
public void main(String[] args)
{
executor.scheduleAtFixedRate(new ScheduledThreadPoolExecutorTest().new MyTask(), 0, 5, TimeUnit.SECONDS);
}
}
Bien cancelado fuera del hilo:
public class ScheduleTest {
@Test
public void testCancel() throws Exception {
final ScheduledThreadPoolExecutor EXECUTOR = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(2);
ScheduledFuture f1 = EXECUTOR.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Im alive 1");
}
}, 0, 1, TimeUnit.SECONDS);
ScheduledFuture f2 = EXECUTOR.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Im alive 2");
}
}, 0, 2, TimeUnit.SECONDS);
Thread.sleep(10000);
f1.cancel(true);
System.out.println("f1 cancel");
Thread.sleep(10000);
f2.cancel(false);
System.out.println("f2 cancel");
Thread.sleep(10000);
}
}
A veces, el hilo no se podía cancelar, esto se resuelve generalmente a través de un volatile boolean isCancelled;
ejecuta esta prueba, imprime 1 2 3 4 5
y se detiene
public class ScheduledThreadPoolExecutorTest {
static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no
static ScheduledFuture<?> t;
static class MyTask implements Runnable {
private int attempt = 1;
public void run() {
System.out.print(attempt + " ");
if (++attempt > 5) {
t.cancel(false);
}
}
}
public static void main(String[] args) {
t = executor.scheduleAtFixedRate(new MyTask(), 0, 1, TimeUnit.SECONDS);
}
}
CountDownLatch
es un enfoque alternativo. Cuando se complete el hilo, llame a countDown()
en el pestillo. El subproceso de llamada llama a latch.await()
hasta que se completen todos los subprocesos. En ese punto, llama a ExecutorService.shutdownNow()
para que tu hilo principal no se convierta en un zombie.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExecutorTest {
static int i = 0;
public static void main(String[] args) throws Exception {
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
final CountDownLatch latch = new CountDownLatch(1);
executor.scheduleAtFixedRate(() -> {
System.out.println(++i);
if (i > 4) {
latch.countDown();
}
}, 0, 100, TimeUnit.MILLISECONDS);
latch.await();
executor.shutdownNow();
}
}