CountDownLatch и остановка потока

 
0
 
Java
ava
xbarmaglot | 17.02.2013, 14:07
Есть поток, который должен засыпать на длительное время, но который нужно быстро остановить по требованию.
Решил использовать CountDownLatch.


        private final CountDownLatch    m_sync = new CountDownLatch(1);

    public final boolean stopThread()
    {
        try
        {
            m_sync.countDown();
            super.join();        
            return true;
        }
        catch (Exception ex)
        {
            Log.e(this.getClass().getName(), ex.getMessage());
            return false;
        }
    }
    @Override
    public void run()    
    {            
        try
        {
            do
            {
                              ...
            }
            while (!m_sync.await(900, TimeUnit.SECONDS)); // 15 мин.
        }
        catch (Exception ex)
        {
            Log.e(this.getClass().getName(), ex.getMessage());
        }
    }    



Это нормальное решение или можно как еще ?
Ответы (10)
ava
jk1 | 17.02.2013, 21:23 #
Цитата


Это нормальное решение



Нет. Если хочется сделать на голых потоках, то лучше пользоваться стандартными механизмами прерывания работы потока:


public class Task implements Runnable {

    @Override
    public void run() {
        try {
            do {
                System.out.println("Doing some work");
                Thread.sleep(1000);
            } while (true);
        } catch (InterruptedException e) {
            System.out.println("Stopping thread");
        }
    }


    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Task());
        thread.start();
        Thread.sleep(5500);
        thread.interrupt();
    }
}


А вообще подобные вещи принято делать на таймерах, чтобы избежать возможных проблем при ручном разруливании взаимодействия потоков:


import java.util.Timer;
import java.util.TimerTask;

public class Task extends TimerTask {

    @Override
    public void run() {
        System.out.println("Doing some work");
    }

    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new Task(), 1000, 1000);
        Thread.sleep(5500);
        timer.cancel();
    }
}
ava
xbarmaglot | 17.02.2013, 21:50 #
Цитата (jk1 @  17.2.2013,  21:23 findReferencedText)
Нет. Если хочется сделать на голых потоках, то лучше пользоваться стандартными механизмами прерывания работы потока:

а чем мой способ плох ? Какие причины проблемм ?

Добавлено позднее:
Ведь я корректно завершаю поток...

Добавлено позднее:
Да и после thread.interrupt() нужен ли join() ?
ava
jk1 | 17.02.2013, 22:58 #
Цитата


а чем мой способ плох ? Какие причины проблемм ?



1. Тем, что использует нестандартный подход без необходимости. Совершенно типовая задача решается нестандартным способом.
2. Тем, что использует CountDownLatch не по назначению. Образно выражаясь, Вы копаете яму молотком. Теоретически это возможно, но непонятно зачем - проще взять лопату.
3. Тем, что это просто велосипед, в котором Вашим коллегам придется потом разбираться. Для периодических задач принято использовать таймеры или пулы потоков с функциональностью таймеров. Кстати все они в Java оборудованы возможностью прерывания. Зачем писать свое когда уже есть готовое?

Цитата


Да и после thread.interrupt() нужен ли join() ? 


Нет. Он и в исходном варианте не нужен. Зачем тормозить без причины вызывающий поток?
ava
xbarmaglot | 18.02.2013, 09:26 #
c join понятно.
А вот поток у меня засыпает

            do {
                System.out.println("Doing some work");
                Thread.sleep(900 * 1000);
            } while (true);


но нифига не просыпается.
То есть я не вижу периодических записей "Doing some work"
В чем может быть проблема ?
ava
korian | 18.02.2013, 19:00 #
Цитата (xbarmaglot @  18.2.2013,  08:26 findReferencedText)
но нифига не просыпается.

То есть я не вижу периодических записей "Doing some work"

из привиденного куска кода - так не бывает. Поток запущен?
ava
xbarmaglot | 19.02.2013, 09:12 #
понятно

Есть еще несколько вопросов:
1. Как усыпить поток до ожидания прерывания ? То есть нужно в отдельном потоке запустить
потоковый объект и ждать завершения потока. А если он останавливается, то в блоке finally остановить поток.
Просто Thread.sleep(0xFFFFFFFF) как-то кривовато smile
2. Если поток не запущен, то к чему приведет внешний вызов interrupt ? Ведь блок try/catch внутри потока.
Будет ли исключение брошено ? Если да, то уго нужно ловить извне ?
3. Если потоковый объект запущен, то будет ли он приостановлен, если сам поток засыпает на ожидании прерывания ?
ava
jk1 | 19.02.2013, 17:30 #
Цитата


1. Как усыпить поток до ожидания прерывания ? То есть нужно в отдельном потоке запустить 

потоковый объект и ждать завершения потока. А если он останавливается, то в блоке finally остановить поток.

Просто Thread.sleep(0xFFFFFFFF) как-то кривовато 



А зачем нужен поток который ждет, пока его не прервут?

Цитата


2. Если поток не запущен, то к чему приведет внешний вызов interrupt ? Ведь блок try/catch внутри потока.



Вызывающий код получит IllegalThreadStateException

Цитата


3. Если потоковый объект запущен, то будет ли он приостановлен, если сам поток засыпает на ожидании прерывания ? 



Если поток ушел в sleep, то, очевидно, он не выполняется. Или под "приостановкой" Вы понимаете что-то другое?
ava
xbarmaglot | 19.02.2013, 18:54 #
Цитата (jk1 @  19.2.2013,  17:30 findReferencedText)
А зачем нужен поток который ждет, пока его не прервут?

чтоб можно было использовать блок try/finally

Цитата (jk1 @  19.2.2013,  17:30 findReferencedText)
Вызывающий код получит IllegalThreadStateException

понятно

Цитата (jk1 @  19.2.2013,  17:30 findReferencedText)
Если поток ушел в sleep, то, очевидно, он не выполняется. Или под "приостановкой" Вы понимаете что-то другое? 

поток создает объект, который работает. А сам засыпает. Так вот будет ли объект тоже спать ?
ava
xbarmaglot | 21.02.2013, 19:13 #
еще вопрос - можно ли после interrupt снова запускать поток ? Или его нужно пересоздавать ?
ava
jk1 | 24.02.2013, 22:21 #
interrupt не завершает работу потока, он просто выставляет флаг. Поток, прочитав этот флаг, может сам завершить свою работу (вернуть управление из метода run), если захочет. После завершения работы потока повторный его запуск уже невозможен.
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
  korian ava  jk1   xbarmaglot
advanced
Отправить