2013-06-05 86 views
1

我有如下一個下面的代碼:線程不能繼續運行

new Thread(new Test1Runnable()).start();  // Line (a) 

public class Test1Runnable implements Runnable { 

    public void run() { 
     Test2Runnable task1 = new Test2Runnable(); 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 

      try { 
       executor.submit(task1); 

       while(true) { 
        if(task1.isDone()) { 
         break; 
        } 
        // Thread.sleep(2000); // Line (b) 
       } 

       if(!task1.hasError()) { // Line (c) 
        executor.submit(new Test3Runnable()); 
       } 
      } catch(Exception ex) { 
       if(executor != null) { 
        executor.shutdown(); 
       } 
      } 
    } 
} 

public class Test2Runnable implements Runnable { 

    private Exception error; 
    private boolean done; 

    public void run() { 
     reset();   
     doRun(); 
     done = true; 
    } 

    protected void doRun() { 
     try{ 
      // ... 
      // .... 
     } catch(Exception ex) { 

     } 
    } 

    private void reset() { 
     error = null; 
     done = false;   
    } 

    public boolean isDone() { 
     return done; 
    } 

    public boolean hasError() { 
     return getError() != null || getNonSuccess() > 0; 
    } 

    public Exception getError() { 
     return error; 
    } 

} 

我有一個問題,當我在線路運行Test1Runnable(a)和註釋行(B),則朝不保夕,而不是運行線(C)。如果我取消註釋行(b)或者我在行(c)添加斷點並激活遠程調試,那麼線程將繼續正常運行。任何人都可以給我一些關於這方面的建議嗎?爲什麼線程不能繼續運行?所有的線程運行沒有任何異常。

+0

Test2Runnable.isDone()是否依賴於volatile變量?這應該。而且,當你在while(true)循環中進行輪詢時,輪詢緊密循環中的狀態變化是非常浪費的。要知道任務何時完成,您應該考慮保留由executor.submit()返回的Future對象,並調用Future.get()。 – JimN

+0

可能你無法很好地控制tour'task1#isDone'方法的返回值,因此會產生無限循環。 –

+0

啓發我們,爲什麼不等待由'ExecutorService.submit'call返回的'Future',而不是輪詢:請參閱'Future .get'?輪詢不是檢查線程/任務終止的好主意。 –

回答

1

看起來你在這裏有一個競爭條件,所以執行的結果取決於定時,啓用調試等等。發佈的代碼或多或少都很好,錯誤很可能在Test2Runnable類中。我想有一些標誌(isDone,hasError)有可見性問題。嘗試聲明它們不穩定。 請在這裏添加Test2Runnable代碼,我將能夠給出更準確的答案。

+0

謝謝JK1。我已經發布了Test2Runnable的詳細信息 – Barcelona

+0

謝謝。現在很明顯,Test2Runnable中的字段缺少正確的同步,無法從其他線程正確看到。嘗試使「完成」和「錯誤」字段變爲易失性,或同步所有讀/寫訪問權限,它應該做的竅門 – Jk1

+0

我必須輪詢isDone()方法以確保task1成功完成,沒有任何錯誤,然後繼續運行下一個任務。有沒有更好的解決方案來實現這一目標? – Barcelona