Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Ожидание завершения потока


Автор: gpepsi 14.8.2012, 10:50
У меня есть поток, который должен работать как таймер.
Он должен спать и просыпаться через определенное время.
Не использовал таймер, т.к. операции потока могут быть очень длительными.

Так вот если поток ждет своего времени слишком долго, то его тогда сложно будет остановить (долго ждать).
Появилась идея, что поток должен ждать на неком объекте синхронизации.

Код

class SomeThread extends Thread
{
    private final CountDownLatch  m_object = new CountDownLatch(1);

    @Override
    public void run()
    {
         // Если не дождались завершения
         while (!m_object.await(10 * 60, TimeUnit.SECONDS))
         {
             // Делаем свою грязную работу
         }
    }

    final void stopThread()
   {
        m_object.countDown();
        this.stop();
        this.join ();
   }
}


Тогда поток ждет 10 минут. Если не дождался завершения, то выполняет работу.
А если дождался, то поток завершается.
Но метод Thread.stop объявлен как final и не является абстрактным, для того, чтобы его можно было перегрузить.

Правильно ли я мыслю, или можно сделать как по-другому с перегрузкой абстрактных методов ?

Автор: Ares4322 14.8.2012, 12:06
Есть такая штука - http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
Он создается так - http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool(int)
В ScheduledExecutorService можно задать с какой задержкой или с каким периодом будет запускаться поток.
Или это не то?

Автор: jk1 14.8.2012, 12:06
Цитата

Не использовал таймер, т.к. операции потока могут быть очень длительными.


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

Код

final Executor executor = Executors.newCachedThreadPool();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        //long task
                    }
                });
            }
        }, 1000);


код конечно надо причесать, но общая идея должна быть ясна

Добавлено через 3 минуты и 39 секунд
Цитата

Есть такая штука - http://docs.oracle.com/javase/7/docs/api/j...torService.html
Он создается так - http://docs.oracle.com/javase/7/docs/api/j...ThreadPool(int)
В ScheduledExecutorService можно задать с какой задержкой или с каким периодом будет запускаться поток.
Или это не то? 


Зависит от требований.
Если нужно, чтобы между концом предыдущего выполнения и началом следующего был фиксированный интервал времени, то да, ScheduledExecutorService#scheduleWithFixedDelay подходит.
Если нужно, допустим, каждую минуту запускать задачу заново вне зависимости от того, завершилась прошлая или нет, то ScheduledExecutorService этого не умеет.

Автор: Ares4322 14.8.2012, 12:16
jk1, не так.
scheduleAtFixedRate() - запускает потоки с разницей между запусками, равной period.
scheduleWithFixedDelay() - запускает потоки с разницей между запуском одной и началом другой, равной delay.
Соответственно, для первого случая нужно, чтобы были свободные потоки в пуле, если время выполнения задачи превышает period.

Автор: gpepsi 14.8.2012, 12:18
а как завершить выполнения потока ?

Автор: jk1 14.8.2012, 12:20
Цитата

jk1, не так.


Правда?

Цитата

scheduleAtFixedRate()

Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on. If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.


Как видно из доков оно будет тормозить последующие вызовы при затягивании предыдущих, а не запускать их в параллель.

Автор: Ares4322 14.8.2012, 12:26
jk1, да, все так. Прошу прощения за дезинформацию.

Для остановки можно получить ScheduledFuture у scheduleAtFixedRate() и вызвать cancel().

Автор: gpepsi 14.8.2012, 16:03
понятно - спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)