guava ThreadPool + CountDownLatch встречает IllegalMonitorStateException - PullRequest
0 голосов
/ 08 декабря 2018

Я пытался протестировать одновременный пакет гуавы, как показано ниже.

Я ожидаю, что созданный пул потоков выполнит экземпляр класса "Runnable" и затем будет ждать завершения.

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;
public class MyTest {
    public static void main(String [] args) {
        final CountDownLatch latch = new CountDownLatch(2);
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("UseCountDownLatch").build();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10,
                10,
                100,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                namedThreadFactory);
        executor.execute(new Runnable() {
            @Override
            public void run() {
                latch.countDown();
            }
        });
        try {
            executor.wait();
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Но на самом деле он печатает:

Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at UseCountDownLatch.main(MyTest.java:28)

Если я уберу строку

executor.wait();

Тогда программа зависнет там без остановки.Так где же я ошибся, чтобы изящно выполнить и завершить задачу в ThreadPool?Как это исправить?

Спасибо большое.

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

не стоит ждать исполнителя;защелка - это ваш механизм синхронизации.И ваше ожидание защелки никогда не завершится, потому что вы выполняете обратный отсчет только один раз (вы выполняете одну задачу для обратного отсчета, но ваша защелка была инициализирована с помощью 2).

0 голосов
/ 08 декабря 2018

Замечание о том, что вы не увеличили счетчик для обратного отсчета, достаточно правильно, +1 от меня.Чтобы исправить это, вы можете добавить еще одну задачу, такую ​​как Runnable, которую вы передаете в метод execute.

Почему вы получаете IllegalMonitorStateException: это потому, что вы вызвали wait для исполнителя, не удерживая неявную блокировку объекта executor.Это не то, что имеет смысл для вас сделать здесь.Возможно, вы перепутали его с awaitTermination ?

логическим значением awaitTermination (длительный тайм-аут, единица TimeUnit), генерирует InterruptedException

Блокирует, пока все задачи не завершат выполнение после запроса на отключениеили происходит тайм-аут, или текущий поток прерывается, в зависимости от того, что произойдет раньше.

Но в этом случае просто вызовите shutdown для исполнителя, чтобы он знал, что новые задачи не приходят, и он может завершиться.рабочие потоки после завершения запущенных задач.

...