2014-01-24 57 views
0

我有我的主線程正在創建新線程的實例。這個新線程創建了一個節拍器的實例。如果我嘗試通過點擊主線程上的按鈕來調用節拍器play()方法,那麼節拍器開始,但整個應用程序凍結。從主線程凍結應用程序調用工作線程中的應用程序

主要活動代碼:

public class HomeScreen extends Activity { 

MetroThread metronome; 


/*** onCreate ***/ 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_home_screen); 

metronome = new MetroThread(); 
metronome.start(); 
} 

/*** button clicks ***/ 

public void st44BtnClick(View v) 
{ 
if(metronome.myMetronome==null) 
{ 
    metronome.playMetronome(); 
} 
else if(metronome.myMetronome!=null) 
{ 
    metronome.stopMetronome(); 
} 
} 

節拍器線程代碼:

public class MetroThread extends Thread 
{ 
//create instance of the metronome 
public Metro myMetronome; 

public void run() 
{ 
System.out.println("metroThread started"); 
} 

/*** play metronome ***/ 
public void playMetronome() 
{ 
myMetronome = new Metro(); 
myMetronome.bpm = 200; 
myMetronome.beat = 7; 
myMetronome.beatSound = 2000; 
myMetronome.sound = 2600; 
myMetronome.play(); 
} 
/*** stop metronome ***/ 
public void stopMetronome() 
{ 
    myMetronome.stop(); 
myMetronome = null; 
} 

}

如果不是使用一個按鈕來調用playMetronome方法我可以簡單的調用方法從節拍器線程的run()中,它工作正常,並且不會鎖定應用程序。

回答

0

僅僅因爲方法與線程對象關聯並不意味着它在該特定線程上運行。事實上,在這種情況下,您的Metronome線程實際上已經立即退出,只要您從run()方法返回,它就立即結束。

當您調用playMetronome方法時,實際上是從按鈕單擊線程調用它。

你需要做的就是發送一個信號給Metronome線程,然後使它開始播放......或者創建一個新的Metronome並在他們按下按鈕時啓動線程並讓線程始終播放聲音。

+0

在這種情況下,每次點擊按鈕啓動節拍器線程是否是最佳做法?我很擔心線程建立並繼續在後臺運行。 – user2145312

+0

@ user2145312線程在退出運行時消失 - 因此沒有建立。創建線程有一些開銷,所以最好避免它。您還需要考慮如果有人多次重複按下按鈕會發生什麼情況。你應該調查'ExecutorService'。 –

0

這是正確的。這些方法在實際調用線程的線程中執行。由於您正在從UI線程調用這些線程,因此這些線程將在UI線程中執行。嘗試從run()的方法中調用playMetronome

0

工作線程只有從run()調用的代碼才能真正在單獨的線程中工作。現在你正在創建第二個線程,但主線程使所有操作(因爲你是從它的呼叫play()

您可以:

1)添加布爾標誌isPlaying到你的第二個線程,並從mainThread改變它的值

2)在第二個線程的run()開始無限循環,有時在這裏檢查這個標誌。