2010-03-16 76 views
4

我在我的應用程序中使用了多個線程。基本上我有一個組合框,當選擇收件箱時,p1恢復並且p2被暫停,並且在選擇發送時,p2開始並且p1停止。下面是代碼(我敢肯定,它並不完美)Java線程問題

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) { 
       } 
     } 

...因爲它是它現在的工作(我是一個初學者)。在組合框中按下發送時,我得到一個IllegalStateMonitorException。任何人都可以幫我解決問題嗎?

感謝和問候, Krt_Malta

回答

6

的問題是在這裏:

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(); 
    } 
} 

製作的續場volatile這裏,和鏡if語句適當的其他部分。

編輯:回顧一下並與最近面臨的併發錯誤作鬥爭時,實現此模式的任何人都可能面臨無限等待的問題,如果被半鎖定鎖定的對象正在被條件是while循環(這是因爲在評估有條件語句和強制等待語句之間狀態可能會發生變化)。在這種情況下,將同步塊放置在循環外部的外部的上。

0

在這段代碼

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

你上同步p1p2調用notify(),從而導致異常。

-1

你不能在awt事件調度線程中等待,否則將阻止你的整個應用程序。閱讀關於http://en.wikipedia.org/wiki/Event_dispatching_thread

此外,你不應該使用原始線程,除非你真的知道你在做什麼。檢查出http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html並在Executors

+0

上閱讀他沒有在AWT線程中等待。他只是打電話給notify()。此外,我建議調用notifyAll()以確保等待的線程得到通知。 – 2010-03-16 18:06:48

+0

通過在EDT中可以導致等待的任何地方使用同步。這不正確嗎? – Pyrolistical 2010-03-16 18:09:24

+0

這是守衛的鎖;他們的鎖在等待時退回到半鎖。這允許另一個線程抓住鎖,然後恢復另一個線程。無論哪種方式,如果您使用notify()或wait(),則您*必須*鎖定對象。有關詳細信息,請參閱http://www.java2s.com/Code/Java/Threads/Threadnotify.htm。 – 2010-03-16 18:22:52