2009-12-03 64 views
0

我有一個Java小程序。該applet中的一個類正在創建一個線程來完成一些工作,等待30秒完成該工作,如果該工作在30秒內沒有完成,它將設置一個布爾值來停止該線程。等待和布爾變化是同步的塊,這是必要的考慮沒有從這些2在這裏同步需要

System.out.println("Begin Start Session"); 
    _sessionThread = new SessionThread(); 
    _sessionThread.start(); 

    synchronized (_sessionThread) 
    { 
     _sessionThread.wait(30000); 
     _sessionThread._stopStartSession = true; 
    } 

一邊跑,爲什麼我不能只是這樣做,而不是沒有其他線程。

System.out.println("Begin Start Session"); 
    _sessionThread = new SessionThread(); 
    _sessionThread.start(); 

    _sessionThread.wait(30000); 
    _sessionThread._stopStartSession = true; 

SessionThread運行方法。調用一個JNI方法來調用一個dll來打開一個程序窗口。

public void run() 
{ 
    try 
    { 
     startExtraSession(); 
    } 
    catch (Throwable t) 
    { 
     t.printStackTrace(); 
    } 
     notify(); 
} 


private native void openSessionWindow(String session_file); 

private void startExtraSession() 
{ 
    final String method_name = "startExtraSession"; 

    String title = _sessionInfo._title; 
    long hwnd = 0; 

    openSessionWindow(_sessionInfo._configFile); 

    try 
    { 
     //Look for a window with the predefined title name... 
     while ((hwnd = nativeFindWindow(title)) == 0 && !_stopStartSession) 
     { 
      Thread.sleep(500); 
    } 
    } 
    catch(Throwable t) 
    { 
     t.printStackTrace(); 
    } 
} 

1.是否真的需要同步?
2.除了使用線程之外,還有更好的方法來完成這個嗎?

回答

3

給定的線程需要擁有一個對象上的鎖,以便能夠調用wait(long)。這是通過在所述對象上使用同步塊來實現的。

請參閱J2SE specification關於使用wait

獲取Java中的鎖定/監視器可以以各種方式來完成:

  • 在​​(非靜態)的方法,該線程擁有由this引用的對象上的監視器。
  • static synchronized方法中,線程在定義所述方法的類的Class<?>描述符上擁有監視器。
  • synchronized(x)塊中,該線程擁有一個顯示器x。如果

該鎖將被釋放:

  • 你得到同步代碼塊之外(無論是方法,靜態方法,或明確的塊)。
  • 您已撥打wait()或其中一個變體(您將在方法返回之前重新獲取它)。

這兩個列表都可能會省略特定情況,但應覆蓋至少大部分典型用例。

+0

如果線程由班級擁有,他將從中調用同步部分,是否不符合此要求?自從我的Java時代已經很長時間了,所以請賜教。 – 2009-12-03 20:21:31

+0

如果您在任何同步方法或任何同步塊之外,則您不擁有任何監視器,因此無法調用「wait」。讓我編輯我的答案在鎖定/監視器採集上更清晰一些。 – Romain 2009-12-04 08:12:46

0

請問您可以發佈SessionThread代碼嗎?你不能等待,如果你不擁有鎖,所以你需要同步(_sessionThread)來做_sessionThread.wait(30000);不知道_sessionThread有什麼。_stopStartSession = true;

+0

我猜布爾值殺死了第二個線程中的一個循環。 – 2009-12-03 20:23:56

+0

是的,如果第二個線程運行時間超過30秒,那麼當布爾變化時,while將會中斷。發佈其他代碼以及 – Keibosh 2009-12-03 20:45:58

1

有你需要​​調用wait

的​​一個很簡單的理由可以確保沒有人呼籲的同時notifynotifyAll你打電話wait

例如:線程1

synchronized(obj) 
{ 
    triggerActionOnThread2(); 
    obj.wait(); 
} 

線程2(由triggerActionOnThread2觸發)

... 
    synchronized(obj) 
    { 
     obj.notify(); 
    } 

如果沒有synchronized塊,那麼notify可能之前(或期間)的wait發生,然後wait錯過了notify,你可以掛線程1

想象上面的代碼塊沒有​​塊,並想象如果線程2在等待被調用之前一直執行通知。

順便說一句,當這個工作涉及多線程編程時,我會問這個關於面向Java工程師的問題。

+0

似乎同步是出現異常的明確目的? – 2009-12-04 02:32:42

+0

不完全。同步是爲了確保正確的順序。等待/通知基本上是一個信號量。你想確保一個線程先等待,另一個線程再次通知。 – karoberts 2009-12-04 04:13:58

+0

我的意思是在給出的例子中。但在再次查看之後,notify()是try/catch之後的。感謝您的輸入(或者是您的輸出?)! – 2009-12-04 13:12:54

0

如果布爾值是線程之間唯一的共享狀態,那麼聲明布爾型瞬態將保證在線程之間看到它的更改,就像訪問布爾值的同步塊一樣。