Re[3]: Отмена выполнения задачи в отдельном потоке и FutureT
От: abch-98-ru Россия  
Дата: 18.03.09 15:39
Оценка:
А>Как я уже писал выше. Между завершением предыдущей задачи и началом новой мне надо выполнять ряд действий по деинициализации. Для этого мне обязательно надо знать, что задача остановлена.
может это тоже задача?
Re[4]: Отмена выполнения задачи в отдельном потоке и FutureT
От: Аноним  
Дата: 18.03.09 16:21
Оценка:
Здравствуйте, mkizub, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


А>>Как я уже писал выше. Между завершением предыдущей задачи и началом новой мне надо выполнять ряд действий по деинициализации. Для этого мне обязательно надо знать, что задача остановлена.


M>Ну тогда код задачи должен быть вроде

M>
M>public void run() {
M>  GlobalDaemon.BUSY = true;
M>  try {
M>    ...
M>  } finally {
M>    GlobalDaemon.BUSY = false;
M>    // optionally notify waiters with Object.notifyAll or firering an event
M>  }
M>}
M>


Я использую для этого CountDownLatch в примере и обхожусь без notifyAll и прочих вещей связанных с volotaile переменными.
Re[4]: Отмена выполнения задачи в отдельном потоке и FutureT
От: runtime2  
Дата: 18.03.09 16:27
Оценка:
Здравствуйте, mkizub, Вы писали:

M>Здравствуйте, runtime2, Вы писали:


R>>При использовании Thread мне надо будет пересоздавать каждый раз поток. Экзекутор позволяет использовать один и тот же поток для запуска задач. Таск я использую для отмены и для работы с исключениями. Хотя может он и не к месту здесь.


M>Зачем пересоздавать? Создайте один раз и пусть он себе крутится. Вроде того, как это описано в javadoc-е для java.util.concurrent.BlockingQueue


В случае с Executor получается проще писать вспомогательные классы и прочее. Например, чтобы послать сообщение потокам об остановке достаточно вызвать shutdownNow() у реализации ExecutorService. В любом случае, рекомендуется использовать executors framework, вместо низкоуровневой работы с Thread.
Re[4]: Отмена выполнения задачи в отдельном потоке и FutureT
От: runtime2  
Дата: 18.03.09 16:29
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

А>>Как я уже писал выше. Между завершением предыдущей задачи и началом новой мне надо выполнять ряд действий по деинициализации. Для этого мне обязательно надо знать, что задача остановлена.

A9R>может это тоже задача?

Да задача, но так как она связана с GUI, то должна выполняться в главном потоке.
Re[2]: Отмена выполнения задачи в отдельном потоке и FutureT
От: KRA Украина  
Дата: 18.03.09 16:32
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

А>Написал класс

А>
А>public class CallableControl<V> implements Callable<V> {

А>    
А>    public void waitDone() throws InterruptedException {
А>        //задача еще не начала выполняться
А>        if( latch.getCount() == 2 ) {
А>            return;
А>        }
А>        latch.await();
А>    }

А>}
А>

А>То есть, вроде бы, все правильно. Только я не знаю насколько CallableControl корректен с точки зрения многопоточности.

Некорректен. Есть ситуация гонок в выделеной строке. Вполне возможен такая последовательность выполнения

Поток 1                                     Поток 2
выполнили executor.execute()
                                            зашли в CallableControl.call
выполнили sleep()
выполнили future.cancel()
зашли в future.waitDone()
выполнили latch.getCount()
                                            выполнили latch.countDown()


итог — основной поток решил, что задача закончилась, а она ещё выполняется.
Re[5]: Отмена выполнения задачи в отдельном потоке и FutureT
От: mkizub Литва http://symade.tigris.org
Дата: 18.03.09 16:50
Оценка:
Здравствуйте, runtime2, Вы писали:

R>В любом случае, рекомендуется использовать executors framework, вместо низкоуровневой работы с Thread.


Понимаете, слово фреймворк переводится на русский как "каркас, остов". Так этот каркас может оказаться совсем не от вашей задачи.
Как вы заметили с get-ом, этот фреймворк не расчитан на подобное использование. Он расчитан на автоматическое выполнение независимых задач, последовательно или параллельно. Чтоб его пофиксить вы должны будете залезть туда очень глубоко, и не факт, что вообще сможете добиться этой функциональности.

ЗЫ Когда я читаю слова подобные "В любом случае, рекомендуется использовать" — у меня сразу желчь разливается. Тут в каждом слове ошибка. Не может быть единых рекомендаций на все (любые) случаи. И ссылки на неназванного, но видимо очень крутого, авторитета — особенно раздражают. Так что я умываю руки, что мог посоветовать, уже написал.
SOP & SymADE: http://symade.tigris.org , блог http://mkizub.livejournal.com
Re[3]: Отмена выполнения задачи в отдельном потоке и FutureT
От: runtime2  
Дата: 18.03.09 16:51
Оценка:
Здравствуйте, KRA, Вы писали:

KRA>Здравствуйте, Аноним, Вы писали:


А>>Написал класс

А>>
А>>public class CallableControl<V> implements Callable<V> {

А>>    
А>>    public void waitDone() throws InterruptedException {
А>>        //задача еще не начала выполняться
А>>        if( latch.getCount() == 2 ) {
А>>            return;
А>>        }
А>>        latch.await();
А>>    }

А>>}
А>>

А>>То есть, вроде бы, все правильно. Только я не знаю насколько CallableControl корректен с точки зрения многопоточности.

KRA>Некорректен. Есть ситуация гонок в выделеной строке. Вполне возможен такая последовательность выполнения


KRA>
KRA>Поток 1                                     Поток 2
KRA>выполнили executor.execute()
KRA>                                            зашли в CallableControl.call
KRA>выполнили sleep()
KRA>выполнили future.cancel()
KRA>зашли в future.waitDone()
KRA>выполнили latch.getCount()
KRA>                                            выполнили latch.countDown() 
KRA>


KRA>итог — основной поток решил, что задача закончилась, а она ещё выполняется.


Да, согласен. Так и знал что-то здесь не то. Теперь надо подумать как исправить эту штуку.
Re[3]: Отмена выполнения задачи в отдельном потоке и FutureT
От: runtime2  
Дата: 19.03.09 08:30
Оценка:
Здравствуйте, KRA, Вы писали:

KRA>Здравствуйте, Аноним, Вы писали:


А>>Написал класс

А>>
А>>public class CallableControl<V> implements Callable<V> {

А>>    
А>>    public void waitDone() throws InterruptedException {
А>>        //задача еще не начала выполняться
А>>        if( latch.getCount() == 2 ) {
А>>            return;
А>>        }
А>>        latch.await();
А>>    }

А>>}
А>>

А>>То есть, вроде бы, все правильно. Только я не знаю насколько CallableControl корректен с точки зрения многопоточности.

KRA>Некорректен. Есть ситуация гонок в выделеной строке. Вполне возможен такая последовательность выполнения


KRA>
KRA>Поток 1                                     Поток 2
KRA>выполнили executor.execute()
KRA>                                            зашли в CallableControl.call
KRA>выполнили sleep()
KRA>выполнили future.cancel()
KRA>зашли в future.waitDone()
KRA>выполнили latch.getCount()
KRA>                                            выполнили latch.countDown() 
KRA>


KRA>итог — основной поток решил, что задача закончилась, а она ещё выполняется.


Вот исправленный вариант. Но может еще что не так.
public class CallableControl<V> implements Callable<V> {

    private final CountDownLatch latch = new CountDownLatch(2);

    private final Callable<V> callable;

    public CallableControl(Callable<V> callable) {
        this.callable = callable;
    }

    public V call() throws Exception {
        if( !prepareForRunning() ) {
            return null;
        }
        try {
            V result = callable.call();
            return result;
        } finally {
            latch.countDown();
        }
    }

    public void waitDone() throws InterruptedException {
        if( isAlreadyRunning() ) {
            latch.await();
        }
    }

    synchronized private boolean isAlreadyRunning() {
        if( latch.getCount() == 2 ) {
            latch.countDown();
            return false;
        }
        return true;
    }

    synchronized private boolean prepareForRunning() {
        if( latch.getCount() == 2 ) {
            latch.countDown();
            return true;
        }
        return false;
    }

}
Re[5]: Отмена выполнения задачи в отдельном потоке и FutureT
От: abch-98-ru Россия  
Дата: 20.03.09 08:46
Оценка:
А>>>Как я уже писал выше. Между завершением предыдущей задачи и началом новой мне надо выполнять ряд действий по деинициализации. Для этого мне обязательно надо знать, что задача остановлена.
A9R>>может это тоже задача?

R>Да задача, но так как она связана с GUI, то должна выполняться в главном потоке.


если "главный поток" — это edt и там что-то ждёт блокируясь — завершения другого потока — это не гуд. но — это отвлечение.

если принципиально делать надо в двух потоках — главном и вспомогательном, то имхо правильно — это два single thread executor-а — для главного и вспомогательного и message-passing — размещением тасков в них.

т.е. из главного запустили таску на loadImage в вспомогательном и отпустили главный. при появлении реквеста на новую задачу, отменяющую предыдущую, — сделали предыдущей(запущенной во вспомогательном) cancel — разместили во вспомогательном executor-е таску, проверяющую на свой старт, состояние предыдущей заканселленной таски + размещение деинициализующей таски на предыдущую в main потоке (по необходимости) + из main потока же в деиниц. таске или отдельно запустили новую задачу в вспомогательном ex.... и тд.

всё последовательно — но всё thread-ы работают не блокируясь. если же надо блокируясь в главном thread-e — то да — можно latch-ами и по разблокированию действововать дальше. но если и есть у вас там блокирование в gui, то, надеюсь, не в edt.

удач,
Re[6]: Отмена выполнения задачи в отдельном потоке и FutureT
От: runtime2  
Дата: 20.03.09 10:13
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

A9R>если принципиально делать надо в двух потоках — главном и вспомогательном, то имхо правильно — это два single thread executor-а — для главного и вспомогательного и message-passing — размещением тасков в них.


Главный поток, это действительно EDT. Кроме него есть два вспомогательных, которые завязаны на действия пользователя в GUI.

A9R>т.е. из главного запустили таску на loadImage в вспомогательном и отпустили главный. при появлении реквеста на новую задачу, отменяющую предыдущую, — сделали предыдущей(запущенной во вспомогательном) cancel — разместили во вспомогательном executor-е таску, проверяющую на свой старт, состояние предыдущей заканселленной таски + размещение деинициализующей таски на предыдущую в main потоке (по необходимости) + из main потока же в деиниц. таске или отдельно запустили новую задачу в вспомогательном ex.... и тд.


То есть получается EDT поток и два дополнительных потока?

A9R>всё последовательно — но всё thread-ы работают не блокируясь. если же надо блокируясь в главном thread-e — то да — можно latch-ами и по разблокированию действововать дальше.


Спасибо, теперь я знаю, что все делаю правильно

A9R>но если и есть у вас там блокирование в gui, то, надеюсь, не в edt.


Как я уже говорил в EDT, но в этом ничего нет страшного. Это блокировние происходить только как реакция на какое-то действие пользователя. Например, закрытие текущего документа (возможно с сохранением внесенных изменений) и переход к следующему. Для пользователя вполне естественно подождать несколько секунд.
Re[7]: Отмена выполнения задачи в отдельном потоке и FutureT
От: KRA Украина  
Дата: 20.03.09 10:19
Оценка: 1 (1)
Здравствуйте, runtime2, Вы писали:

R>Как я уже говорил в EDT, но в этом ничего нет страшного. Это блокировние происходить только как реакция на какое-то действие пользователя. Например, закрытие текущего документа (возможно с сохранением внесенных изменений) и переход к следующему. Для пользователя вполне естественно подождать несколько секунд.


Одно дело ждать, когда бегут часики и при alt-tab происходит перерисовка и т.д., а другое дело когда весь UI поток заморожен. Последнее не есть хорошо.
Re[7]: Отмена выполнения задачи в отдельном потоке и FutureT
От: abch-98-ru Россия  
Дата: 21.03.09 20:04
Оценка:
A9R>>если принципиально делать надо в двух потоках — главном и вспомогательном, то имхо правильно — это два single thread executor-а — для главного и вспомогательного и message-passing — размещением тасков в них.
R>Главный поток, это действительно EDT. Кроме него есть два вспомогательных, которые завязаны на действия пользователя в GUI.
A9R>>всё последовательно — но всё thread-ы работают не блокируясь. если же надо блокируясь в главном thread-e — то да — можно latch-ами и по разблокированию действововать дальше.
R>Спасибо, теперь я знаю, что все делаю правильно

если надо заблокировать edt и отрубить перерисовки — то да
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.