Отмена выполнения задачи в отдельном потоке и FutureTask
От: runtime2  
Дата: 17.03.09 17:10
Оценка:
У меня есть программка.

Это вспомогательная штука.
public class DaemonThreadFactory implements ThreadFactory {

    /** Фабрика для создания потоков */
    private final ThreadFactory fac = Executors.defaultThreadFactory();

    /** Создает новый поток */
    public Thread newThread(Runnable r) {
        Thread result = fac.newThread(r);
        result.setDaemon(true);
        return result;
    }

}


Вот основная программка.

public class FutureTaskTest {

    public static void main(String[] args) throws Exception {
        new FutureTaskTest().test();
    }

    private final ExecutorService executor =
        Executors.newSingleThreadExecutor(new DaemonThreadFactory());

    public void test() throws Exception {
        Task task = new Task();
        FutureTask<Void> future = new FutureTask<Void>(task);
        task.setFuture(future);
        executor.execute(future);
        Thread.sleep(100);
        future.cancel(true);
        System.out.println("wait");
        try {
            future.get();
        } catch(CancellationException ex) {
            System.out.println("cancellation exception");
        }
        System.out.println("thinking task done");
        Thread.sleep(1000);
    }

}

class Task implements Callable<Void> {

    private Future<Void> future;

    public void setFuture(Future<Void> future) {
        this.future = future;
    }

    public Void call() throws Exception {
        while( !future.isCancelled() ) {
            System.out.println("go");
            try {
                Thread.sleep(500);
            } catch(InterruptedException ex) {
                System.out.println("interrupted");
                Thread.sleep(1000);
                System.out.println("rrrrrrrrrrrr");
            }
        }
        System.out.println("cancelled");
        return null;
    }

}


В методе test() запускаем задачу на выполнение, затем ее отменяем и пытаемся подождать завершения с помошью метода get(). Это не получается, так как метод get() не ждет завершения метода call() класса Task, а сразу генерирует исключение. В результате получаем на консоле следующее.
go
wait
cancellation exception
thinking task done
interrupted
rrrrrrrrrrrr
cancelled


То есть после thunking task done задача еще продолжает работать.
Я хочу чтобы при вызове get() или другого подобного метода, выполнение основного потока блокировалось пока не завершится задача работающая в фоне. Может быть какой-нибудь другой высокоуровневый примитив синхронизации можно применить (чтобы можно было cancel() использовать).

Мне это нужно что-бы последовательно выполнять задачи, но не начинать выполнение следующей задачи без отмены предыдущей.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.