2011-02-23 16 views
0

我有螺紋的煩惱有樂趣;)與線程

我做了一個腳本,我的階級如下:

class Test{ 
TextToSpeech mTts = new TextToSpeech(); 
boolean volatile mVarGlobal = false; 

class T1 extends Thread{ 
    public void run(){ 
     doSomething(){ 
      mVarGlobal = false; 
      // network working...Take a while 
      mTts.speak(...) //Speech information received from Network 
      mVarGlobal = true; 
     } 
    } 
    T1 t = new T1(); 
    t.start(); 

class CheckVarGlobal extends Thread{ 
    public void run(){ 
     if(!mVarGlobal) { 
      text2Speech.speak("something"); 
     } 
    postAtTime(this, 3000); 
    } 
} 
CheckVarGlobal c = new CheckVarGlobal(); 
c.start(); 

}

正如你可以看到我有2個線程運行,一個正在獲取網絡信息,另一個正在收到來自網絡的信息時正在運行。布爾變量mVarGlobal將爲true,然後檢查「CheckVarGlobal」的Thread將因條件(!mVarGlobal)爲false而停止。

的問題是,一旦我從網絡和語音信息的第一個線程的信息,第二個線程仍在運行和speeching「東西」。我想第二線程還沒有意識到CheckVarGlobal是真的......我已經把變量鍵入爲2個線程中使用的volatile。

任何想法,爲什麼會發生,以及如何解決呢?

非常感謝,

最好。 David。

+0

我已經使用與可變mVarGlobal同步getter和setter也嘗試。但它仍然沒有工作:( – Dayerman 2011-02-23 12:07:40

+0

爲什麼你沒有使用OnInitListener和OnUtteranceCompletedListener?你確定:mVarGlobal = true;被調用嗎? – pawelzieba 2011-02-23 12:40:42

+0

使用TextToSpeech.OnUtteranceCompletedListener ??我爲什麼要? 我使用OnInitListender,但它是獨立的這部分的... – Dayerman 2011-02-23 13:01:18

回答

0

Dayerman ......下面是兩個處理一些實驗性的代碼。

編輯。我已編輯的代碼以符合最佳實踐,在一個單一的處理程序使用開關:

private Handler myHandler= new Handler(){ 
     @Override 
     public void handleMessage(Message msg){   
      switch(msg.what){ 
       case 0: 
        if (!isDoneThinking){ 
         editTextConfusedText.setText("Still Thinking "+new Integer(thinkSeconds).toString()); 
         thinkSeconds++; 
         this.removeMessages(0); 
         sendMessageDelayed(obtainMessage(0),1000); 
        } 
        else { 
         thinkSeconds= 0; // reset timer 
        } 
        break; 
       case 1: 
        isDoneThinking= true; 
        onThreadedMessage(msg); 
        break; 
       default: 
        super.handleMessage(msg); 
        break; 
      } 
     } 
    }; 
    public void onThreadMessage(Message msg){ 
     Bundle b= msg.getData(); 
     String encryptedText=""; 
     if (b != null){ 
      encryptedText= b.getString("encryptedText"); 
     } 
     editTextConfusedText.setText(encryptedText); 
     Log.d(TAG,encryptedText); 
    }   

用法:

buttonConfuseText.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // TODO Auto-generated method stub 
        final String inString= editTextPlainText.getText().toString(); 
        isDoneThinking= false; 
        myHandler.sendEmptyMessage(0); // <=== START TIMER 
        Thread thread= new Thread(new Runnable() { // <== START THREADED RUNNABLE 
         public void run() { 
          String outString= encrypt(password,inString); 
          Message msg= myHandler.obtainMessage(1); 
          Bundle b= new Bundle(); 
          b.putString("encryptedText",outString); 
          msg.setData(b); 
          myHandler.sendMessage(msg); 
          Log.d(TAG,outString); 
         } 
        }); 
        thread.setDaemon(true); 
        thread.start(); 
       } 
      }; 
+0

你應該用等待和保護塊來代替。使用睡眠是低效的,因爲它必須等待一個睡眠週期之前,其他線程可以繼續。http://download.oracle.com/javase/tutorial/essential /concurrency/guardmeth.html – 2011-02-24 00:02:08

+0

我想知道代碼在哪裏調用Thread.sleep?我_think_ the m ethod sleep只是延遲的消息循環,每提供一個進度「bar」ms。但我可能是錯的。 – JAL 2011-02-24 06:14:08

+0

嗯。實際上,我測試了代碼。我單獨運行了計時器代碼,UI線程沒有被阻塞。我將計時器代碼和定時運行代碼一起運行,並且可運行代碼完成而不會阻塞,並且UI不會阻塞。 – JAL 2011-02-24 07:22:27

0

你正在檢查中,如果條件的變量,而不是同時condition.That意味着只要它涉及到線程2那個時候只有它是checking.Better在線程2時要使用的條件。

+0

你好ADIT,我想如果我使用它並不重要和IF,與postAtTime方法我做的類似,而一些東西,但酒糟不是while循環侵入性的。問題是,mVarGlobal不改變其值爲true ... – Dayerman 2011-02-23 12:39:25