2012-06-28 68 views
1

在我開發的應用程序中,我有一個正在循環運行的線程。在循環內部,幾個條件被評估,並且取決於這些條件,一個值或另一個值被存儲在SharedPreferences中。提交清除中斷狀態

public void run() 
{ 
    try 
    { 
    SharedPreferences preferences = 
     context.getSharedPreferences("MyPrefs", Activity.MODE_PRIVATE); 

    SharedPreferences.Editor editor = preferences.edit(); 

    while (true) 
    {      
     if (condition1) 
     { 
     editor.putBoolean("mykey", "1"); 
     } 
     else if (condition 2) 
     { 
     editor.putBoolean("mykey", "2");    
     } 
     editor.commit(); 

     if (isInterrupted()) 
     throw new InterruptedException();    

     Thread.sleep(60000); // 60 seconds 
    } 
    } 
    catch (InterruptedException e) 
    { 
    Thread.currentThread().interrupt(); 
    } 
} 

此線程由onResume方法中的Activity啓動,並在onPause方法中中斷。

如果線程是由活動(主線程),當它處於睡眠狀態中斷,一個InterruptedException異常。那沒問題。

但我的問題是,如果活動(主線程)在線程運行(而不是睡眠)時中斷線程。 「中斷標誌」被設置爲true,但是在調用編輯器上的提交之後,該標誌被設置爲false,所以我不能中斷拋出InterruptedException的線程。

我該怎麼辦?

感謝

回答

0

調用editor.commit()將要做I/O操作。如果線程上有掛起的中斷,那麼這可能會中止I/O並清除掛起的中斷。

爲了做你想做的事情,你可能需要在提交時防止線程中斷。您需要同步訪問權限,以便應用程序只能在線程休眠時中斷它。這樣的事情:

// This method will interrupt the thread that is looping ONLY while it is sleeping 
public synchronized void interruptNow() { 
    threadThatIsLooping.interrupt(); 
} 

public void run() { 
try { 
    SharedPreferences preferences = 
     context.getSharedPreferences("MyPrefs", Activity.MODE_PRIVATE); 
    SharedPreferences.Editor editor = preferences.edit(); 
    while (true) { 
     synchronized { 
      // Cannot be interrupted within this block     
      if (condition1) { 
       editor.putBoolean("mykey", "1"); 
      } else if (condition 2) { 
       editor.putBoolean("mykey", "2");    
      } 
      editor.commit(); 
     }    
     Thread.sleep(60000); // 60 seconds 
    } 
} catch (InterruptedException e) { 
    // Do whatever you want here when the thread is interrupted while sleeping 
} 
} 
+0

非常感謝您的回答。我會做你說的。我不明白的是爲什麼「editor.commit」不會拋出InterruptedException而不是清除掛起的中斷。 – Eduardo

0

首先,不這樣做:while (true)

其次,如果線程被中斷:

if (isInterrupted()) 
     throw new InterruptedException();    

     Thread.sleep(60000); // 60 seconds 
    } 
    } 
    catch (InterruptedException e) 
    { 
    Thread.currentThread().interrupt(); 
    } 

它惹人中斷,然後再次中斷線程。這尖叫遞歸,而你的無限while循環並沒有幫助。

+0

我不明白你爲什麼說我不應該做「而(真)」。當在InterruptedException catch塊中時,我再次中斷線程是因爲我必須這樣做。請閱讀下一篇文章http://www.ibm.com/developerworks/java/library/j-jtp05236/index中的「不要吞下中斷」一節。html – Eduardo

+0

包含任何無限循環是非常糟糕的編程習慣。這個循環永遠不會真正結束,並會消耗電池和處理能力。 –

+0

感謝您的回答。我知道一個無限循環不是一個好習慣,但是在我寫的無限循環中,我調用了一個睡眠方法,所以大部分時間線程正在睡眠。另一方面,線程並不總是在運行,而是由其他線程中斷。 – Eduardo

1

我剛剛跑過同樣的問題,發現瞭解決方案。

您可以使用editor.apply()代替editor.commit()

之所以採用()的作品,而不是提交(),是,它在一個新的線程的I/O,因爲它不需要等待返回值:

與承諾(),其同步寫的喜好了持久 存儲,適用()提交其更改立即 SharedPreferences內存,但啓動異步承諾 盤,你會不會通知任何故障。如果 上的另一位編輯員在apply()爲 仍未完成時執行常規提交(),則commit()將會阻塞,直到完成所有異步提交以及提交本身爲止。

+0

感謝您的回答。 – Eduardo