Как правильно избавиться от потока производителя после того, как поток потребителя получит уведомление о синхронизированном изменении и выйдет из строя? - PullRequest
1 голос
/ 16 марта 2012

Насколько я понимаю, после того, как потребитель получит уведомление о синхронизированном изменении переменной, если потребитель Thread выпадет и выйдет, ничто не остановит продюсера. Как правильно утилизировать ветку производителя? Есть ли что-то, что препятствует вызову Thread.interrupt() из метода run() пользователя?

Я пытаюсь сделать следующее:

//in consumer
public void run() {
    synchronized( checkSolution) {
        while (!checkSolution.getIsSolutionValid) {
            try{
                checkSolution.wait()
            } catch( InterruptedException ignore) {}
        } 
        //valid soln received
        System.out.println("reference");
        checkSolution.interrupt();
        doAmazingWorkWithSolution();
    }
    //MARK
}
//in producer (checkSolution)
public synchronized boolean getIsSolutionValid() { return isSolutionValid; }
public void run() {
    while(true) {
        try{
            synchronized( this) {
                if( fSolution.size() != correctSize) {
                    isSolutionValid = false;
                    Thread.sleep(500);
                 } else {
                     System.out.println(" Solution is correct size.");
                     isSolutionValid = true;
                     notifyAll();
                 }  
             }
         } catch(InterruptedException ie) {
             //Thread.currentThread().interrupt();
             return;
    }
    }
}

Теперь вот что я заметил, и я действительно не понимаю:

  1. При любом успешном прерывании устанавливается флаг прерывания производителя, но он выполняет код в блоке else много-много раз, прежде чем окончательно завершить работу. Как я могу избежать спама в операторе if / else во время notify?

  2. если я переместу вызов методов checkSolution.interrupt () и «удивительного труда» в строку, помеченную //MARK, он прерывается значительно медленнее, выполняет потрясающий рабочий вызов, но, как ни странно, никогда не печатает `println (" ссылка " )

  3. Если я удаляю оператор возврата из InterruptedException, он получает прерывание и попадает в блок Exception на один шаг, но спамит оператор else баджиллион раз, а затем снова начинает подключаться снова блок Thread.sleep, как если бы флаг прерывания был сброшен.

  4. Thread.currentThread().interrupt(); в InterruptException продюсера - это то, что я видел в коде других людей, но он, похоже, ничего не делает здесь, включаю я его или нет.

Это мелочи, в которых я запутался. Главный вопрос заключается в том, как максимально эффективно отключить производителя, как можно ближе к потоку потребителей после того, как потребитель получит то, что ему нужно.

1 Ответ

1 голос
/ 16 марта 2012

Я думаю, что вы работаете на слишком низком уровне.Если есть только один производитель и потребитель, вы можете использовать java.util.concurrent.SynchronousQueue для блокировки потребителя, пока производитель не выполнит свою работу.

Для целей Thread.currentThread().interrupt() см. http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html. Этоплохая идея сделать это

catch( InterruptedException ignore) {}

в цикле while.Подробнее в статье по ссылке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...