Проблема с Java - PullRequest
       12

Проблема с Java

4 голосов
/ 16 марта 2010

Я использую несколько потоков в моем приложении. В основном у меня есть поле со списком, и после выбора папки «Входящие» p1 возобновляется, а p2 приостанавливается, а при выборе «Отправить» запускается p2 и останавливается p1. Ниже приведен код (я уверен, что он не идеален)

public void modifyText(ModifyEvent e) {
                if (combo.getText().equals("Inbox"))
                {
                    synchronized(p2) 
                    {
                        p2.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p1.cont = true;
                        p1.notify();
                    }
                }


                else if (combo.getText().equals("Sent"))
                {
                    synchronized(p2) 
                    {
                        p1.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p2.cont = true;
                        p2.notify();
                    }
                }
            }
        });

и для P1 и P2 у меня это внутри циклов while:

synchronized (this) {
            while (cont == false)
                try {
                    wait();
                } catch (Exception e) {
                }
        } 

... Как это сейчас работает (я новичок в потоках). При нажатии Sent в поле со списком я получаю исключение IllegalStateMonitorException. Может ли кто-нибудь помочь мне решить проблему, плз?

Спасибо и всего наилучшего, Krt_Malta

Ответы [ 3 ]

6 голосов
/ 16 марта 2010

проблема здесь:

synchronized(p1)
{
    p2.cont = true;
    p2.notify();
}

Вы делаете p2.notify(), когда у вас нет блокировки на p2 (вы должны держать монитор, чтобы вызвать уведомление об этом). Измените synchronized(p1) на synchronized(p2). Кроме того, вам нужно отменить другое синхронизированное предложение, что также является ошибочным. Итак, в качестве примера:

synchronized(p1) 
{
    p1.cont = false;
    // p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
    p2.cont = true;
    p2.notify();
}

Кроме того, ваш другой код тоже немного неправильный, очень плохая практика - блокировать весь цикл, сделать его немного более атомарным.

while (!cont) {
    synchronized (this) {
       try {
           wait();
       } catch (Exception e) {
       }
    }
}

Дополнительная оптимизация, по возможности избегайте synchronised:

if (p1.cont) {
   synchronized(p1) 
   {
       p1.cont = false;
       // p1.notify(); <- do you need this here?
   }
}
table.removeAll();

if (!p2.cont) {
   synchronized(p2)
   {
       p2.cont = true;
       p2.notify();
   }
}

Сделайте здесь поле cont volatile и отразите для другой части оператора if подходящее значение.

Редактировать: оглядываясь на это и борясь с ошибкой параллелизма, с которой я недавно столкнулся, любой, кто реализует этот шаблон, может столкнуться с проблемой бесконечного ожидания, если условный объект, на который был заблокирован и частично заблокирован, просматривается условным условием. цикла while (это потому, что существует разрыв, в котором состояние может меняться между вычислением условия и наложением оператора ожидания). В этом случае поместите синхронизированный блок на вне цикла.

0 голосов
/ 16 марта 2010

Вы не можете ждать в потоке отправки событий awt, иначе вы задержите все ваше приложение. Читать о http://en.wikipedia.org/wiki/Event_dispatching_thread

Также вы не должны использовать необработанные потоки, если вы действительно не знаете, что делаете. Проверьте http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html и читайте на Исполнители

0 голосов
/ 16 марта 2010

В этом коде

                synchronized(p1)
                {
                    p2.cont = true;
                    p2.notify();
                }

Вы синхронизируете на p1, но вызываете notify() на p2, что приводит к исключению.

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