2012-07-08 66 views
3

我有這個類:關於等待和notifyAll的

public class MyThread implements Runnable { 

    private static boolean canAccess = true; 
    private Thread t; 

    public FirstThread(String name) { 
    t = new Thread(this); 
    t.setName(name); 
    } 

    public void start() { 
     t.start(); 
    } 

    private synchronized void accessed(String name) throws InterruptedException { 
    if (canAccess) { 
     canAccess = false; 
     System.out.println("Accessed " + name); 
     try { 
     Thread.sleep(5000); 
     } catch (Exception e) { 
     } 
     canAccess = true; 
     System.out.println("NOTIFY: " + name); 
     notifyAll(); 
    } 
    System.out.println("WAIT: " + name); 
    wait(); 

    } 

    @Override 
    public void run() { 
    while (true) { 
     try { 
     accessed(Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 
} 

這是我的輸出:

Accessed 1 
WAIT: 3 
WAIT: 5 
WAIT: 7 
WAIT: 9 
WAIT: 0 
WAIT: 2 
WAIT: 4 
WAIT: 6 
WAIT: 8 
NOTIFY: 1 
WAIT: 1 

和我的應用程序凍結(死鎖狀態)。 似乎notifyAll方法不起作用。我的錯誤在哪裏?

我的主課。

public class Main { 

    public static void main(String[] args) { 
    MyThread [] threads = new MyThread[10]; 
    for(int i=0;i<threads.length;i++) { 
     threads[i] = new MyThread(""+i); 
     threads[i].start(); 
    } 

    } 

} 
+1

在構造函數中啓動一個線程很少是個好主意。不知道這是否是問題。例如見:http://stackoverflow.com/questions/5623285/java-why-not-to-start-a-thread-in-the-constructor-how-to-terminate – assylias 2012-07-08 14:56:13

+0

你說得對,但我已經改變了我的代碼,但仍然不起作用。 – CeccoCQ 2012-07-08 14:59:29

+1

我沒有看到,在使用此var的唯一'synchronized'塊中,canAccess首先設置爲'false',然後設置爲'true'。 – 2012-07-08 14:59:59

回答

2

wait意味着線程釋放鎖並進入休眠狀態,直到另一個線程通知它。 notifyAll表示該線程通知所有其他等待當前同步塊中使用的鎖的線程喚醒並嘗試再次獲取該鎖。你的代碼示例沒有任何多線程嘗試獲取同一個鎖的情況,所以使用wait和notifyAll在這裏沒有任何意義。一旦呼叫等待,沒有什麼可以喚醒線程。等待

的典型應用之一,並通知:你可能有很多生產商把東西在一個隊列,消費者線程需要的東西從隊列中。隊列有一個消費者調用的take方法,如果隊列爲空,那麼它調用wait和消費者塊。該隊列有一個put方法,當某事進入隊列時,它會調用notifyAll,以等待消費者線程喚醒。

有在Java教程a producer-consumer example of using wait and notifyAll

1

每個線程都等待它自己的實例,這就是爲什麼它們都卡在一個地方。

如果你有一個private static Object LOCK = new Object();並調用LOCK.wait();和LOCK.notify();這可能是另一回事。

我還懷疑關於訪問()方法同步改性劑。在描述的情況下它沒有用處。我最好修改同步塊中的「canAccess」變量。