2016-02-26 83 views
2

我的老師告訴我不要用停止(),但在Thread類用這種方式:這是我應該停止Java中的線程的方式嗎?

public void pararHilo() { 
    stopHilo = true; 
} 

public void run() { 
    while (!stopHilo) 
     c++; 
} 

據我知道,當pararHilo()被調用的循環結束,因此它退出運行()方法和線程死亡。 事情是,我有一個相當體面的筆記本電腦,當做這個代碼測試(在這裏和在學校)我的機器變得遲滯地獄,我不得不關閉Eclipse ...我錯過了什麼?

整個代碼

public class EjemploHilo { 

    public static void main(String args[]) { 

     HiloPrioridad h1 = new HiloPrioridad(); 
     HiloPrioridad h2 = new HiloPrioridad(); 
     HiloPrioridad h3 = new HiloPrioridad(); 

     //el hilo con mas prioridad contara mas deprisa que los demas 
     h1.setPriority(Thread.MAX_PRIORITY); 
     h2.setPriority(Thread.NORM_PRIORITY); 
     h3.setPriority (Thread.MIN_PRIORITY); 

     h1.start(); h2.start(); h3.start(); 

     try { 
      Thread.sleep(2000); 
      } catch (Exception e) { } 

     h1.pararHilo(); 
     h2.pararHilo(); 
     h3.pararHilo(); 

     System.out.println("h1 (Prioridad Maxima): " + h1.getContador()); 
     System.out.println("h2 (Prioridad Normal): " + h2.getContador()); 
     System.out.println("h3 (Prioridad Minima): " + h3.getContador()); 

     } 

} 

public class HiloPrioridad extends Thread { 

    private int c = 0; 
    private boolean stopHilo= false; 

    public int getContador() { 
     return c; 
    } 

    public void pararHilo() { 
     stopHilo = true; 
    } 

    public void run() { 
     while (!stopHilo) 
      c++; 
    } 

} 
+0

請問你能展示更多代碼嗎?一般來說,你應該在兩次執行之間睡覺,或者更優雅地看看java併發包和執行程序。 – rmalchow

+0

是的,這沒關係。你的機器變得滯後的原因是你運行的是非常緊密的循環,它會循環使用100%的CPU。考慮在您的循環中添加一個'Thread.sleep(100)' –

+0

Thread.sleep(10)可能足以獲得不錯的性能。 –

回答

3

while循環應檢查以下內容:

while (!Thread.currentThread().isInterrupted() && /* more work to do */) { 
    // do more work 
} 

這樣一來,客戶可以調用Thread.interrupt(),這將線程的中斷狀態true

注意:當中斷方法被調用的線程上調用塊如睡眠或等待,阻塞呼叫由一個InterruptedException終止,應進行處理:

try { 
    while (!Thread.currentThread().isInterrupted() && /* more work to do */) { 
     // do more work 
     Thread.sleep(1000); 
    } 
} catch (InterruptedException e) { 
    // thread was interrupted during sleep or wait 
} 
+1

剛剛得到了這個異常,檢查了文檔,並且即將發表評論同樣的事情,謝謝你處理問題的替代方法 –

+0

@Artur:這是正確的方法來做到這一點。 make-your-own-flag方式存在線程無法從睡眠中喚醒或等待的問題,以及構建線程安全結構(java.util.concurrent中包含的組件) )沒有處理。 –

1

是的,但你需要的信號量的變量設置爲volatile

private volatile stopHilo; 

否則正在運行的線程可能再也看不到的分配。

此外,像這樣的緊密循環應該暫停Thread.sleep()或產生Thread.yield()

1

僅當變量可以高速輪詢時,使用請求變量停止線程才適用。

如果您正在調用諸如Thread.sleep()等方法或正在等待其他過程,那麼您的程序將放慢速度,並且請求變量的輪詢率很高。

改爲使用Thread.interrupt()來停止線程。

您可能會發現Oracle's guide爲什麼Thread.stop不贊成有幫助。

您可能會遇到的另一個問題是線程請求變量不是volatile確保您已將其聲明用於預期用途。

private volatile boolean stopHilo = false; 
0

我認爲你需要注意以下幾點:

1)線程優先級。你有一個子線程設置爲HIGH_PRIORITY,而你的主線程沒有設置,所以它應該使用正常的。結果,你的一個子線程比你的主線程具有更高的優先級。由於你有一個無限循環,當你的主線程可能在等待(因爲它是一個較低的優先級)時,這將會吸收你的CPU。

2)和其他人一樣,我會在你的子線程運行方法循環中放入一個小小的睡眠。這將使主線程(和其他人)有時間執行。

3)我個人也不是直接在實踐中引用變量。通常,我會使用get方法,即使在while循環中也會返回變量。這只是一個典型的編碼習慣。如果這個get/set方法對線程很重要,那麼你也可以使它們同步。通過這種方式,一個集合不會在百萬分之一秒發生,反之亦然。一個額外的保護(取決於您的應用使用情況)。就所有主題而言,這些類型的決策需要根據具體情況進行,但需要考慮。你仍然可以調用pararHilo並調用set方法,或者你的主線程可以調用setStopHilo(false)。

你可以試試這三樣東西,看看它是如何工作的嗎?