[英]Thread continues to run after run() method
我在游戲中播放聲音時遇到問題。 當處理聲音播放的線程退出它的run方法時,它不會終止/結束/停止。 我知道這是導致問題的方法,因為當我評論整個事情時,不再創建Threads。 (使用JVisualVM檢查)。 問題是退出run方法后線程不會被終止。 我已經放置了一個print命令來確保它實際到達run()方法的末尾,而且它總是這樣。
但是,當我使用JVisualVM
檢查進程時,對於每個播放的聲音,線程數增加1
。 我還注意到,對於每個播放的聲音,守護程序線程的數量增加了1
。 我不確定守護程序的線程是什么以及它們是如何工作的,但我試圖以多種方式殺死線程。 包括Thread.currentThread
.stop()
.destroy()
.suspend()
.interrupt()
並通過return從run()
方法返回;
在寫這條消息時,我意識到我需要關閉剪輯對象。 這導致沒有創建和維持額外的線程。 然而,現在聲音有時會消失,我不知道為什么。 現在,我可以選擇並行發聲並看到我的cpu被無數個線程超載,或者每當播放新聲音時聲音都會突然結束。
如果有人知道並行播放多個聲音的不同方法或知道我的代碼有什么問題,我將非常感謝任何幫助。
這是方法:
public static synchronized void playSound(final String folder, final String name) {
new Thread(new Runnable() { // the wrapper thread is unnecessary, unless it blocks on the Clip finishing, see comments
@Override
public void run() {
Clip clip = null;
AudioInputStream inputStream = null;
try{
do{
if(clip == null || inputStream == null)
clip = AudioSystem.getClip();
inputStream = AudioSystem.getAudioInputStream(SoundP.class.getResource(folder + "/" + name));
if(clip != null && !clip.isActive())
inputStream = AudioSystem.getAudioInputStream(SoundP.class.getResource(folder + "/" + name));
clip.open(inputStream);
clip.start();
}while(clip.isActive());
inputStream.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
.stop()
.destroy()
或.suspend()
來殺死一個線程。 這些方法已棄用,不應使用。 相反,你應該基本上到達Run()方法的末尾。 這就是Thread.interrupt()
的用途,但你必須支持通過檢查Thread.isInterrupted()
標志來中斷你的線程,然后拋出InterruptedException
並處理它(有關更多詳細信息,請參閱如何停止線程 )。 do-while
循環似乎是多余的。 還有其他好方法可以等待聲音完成播放(如果這是你的目標),並且循環不是其中之一。 while
沒有Sleep
情況下運行多次的while
循環,無緣無故地耗盡CPU。 Close()
( 和 Stop()
) Clip
,以釋放系統資源。 嘗試運行此代碼,看看它是否符合您的要求。 我添加了一些線程方法調用和一些System.out.print
以便您查看每一段代碼的發生時間。 嘗試使用tryToInterruptSound
和mainTimeOut
來查看它如何影響輸出。
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class PlaySound {
private static boolean tryToInterruptSound = false;
private static long mainTimeOut = 3000;
private static long startTime = System.currentTimeMillis();
public static synchronized Thread playSound(final File file) {
Thread soundThread = new Thread() {
@Override
public void run() {
try{
Clip clip = null;
AudioInputStream inputStream = null;
clip = AudioSystem.getClip();
inputStream = AudioSystem.getAudioInputStream(file);
AudioFormat format = inputStream.getFormat();
long audioFileLength = file.length();
int frameSize = format.getFrameSize();
float frameRate = format.getFrameRate();
long durationInMiliSeconds =
(long) (((float)audioFileLength / (frameSize * frameRate)) * 1000);
clip.open(inputStream);
clip.start();
System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound started playing!");
Thread.sleep(durationInMiliSeconds);
while (true) {
if (!clip.isActive()) {
System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound got to it's end!");
break;
}
long fPos = (long)(clip.getMicrosecondPosition() / 1000);
long left = durationInMiliSeconds - fPos;
System.out.println("" + (System.currentTimeMillis() - startTime) + ": time left: " + left);
if (left > 0) Thread.sleep(left);
}
clip.stop();
System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound stoped");
clip.close();
inputStream.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound interrupted while playing.");
}
}
};
soundThread.setDaemon(true);
soundThread.start();
return soundThread;
}
public static void main(String[] args) {
Thread soundThread = playSound(new File("C:\\Booboo.wav"));
System.out.println("" + (System.currentTimeMillis() - startTime) + ": playSound returned, keep running the code");
try {
Thread.sleep(mainTimeOut );
} catch (InterruptedException e) {
e.printStackTrace();
}
if (tryToInterruptSound) {
try {
soundThread.interrupt();
Thread.sleep(1);
// Sleep in order to let the interruption handling end before
// exiting the program (else the interruption could be handled
// after the main thread ends!).
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("" + (System.currentTimeMillis() - startTime) + ": End of main thread; exiting program " +
(soundThread.isAlive() ? "killing the sound deamon thread" : ""));
}
}
Clip
有多長。 這樣我可以讓Thread
Sleep()
並不使用CPU。 我使用額外的isActive()
作為測試來查看它是否真的結束了,如果沒有 - 再次計算剩余時間和Sleep()
(由於兩個事實,聲音可能仍然在第一次Sleep
后播放:1。長度計算不需要考慮微秒,並且2. “你不能假設調用sleep會在指定的時間段內暫停線程” )。 你的代碼就是這個
public static synchronized void playSound(final String folder, final String name) {
new Thread(new Runnable() { // the wrapper thread is unnecessary, unless it blocks on the Clip finishing, see comments
@Override
public void run() {
Clip clip = null;
AudioInputStream inputStream = null;
try{
do{
if(clip == null || inputStream == null){
clip = AudioSystem.getClip();
}
inputStream = AudioSystem.getAudioInputStream(SoundP.class.getResource(folder + "/" + name));
if(clip != null && !clip.isActive()){
inputStream = AudioSystem.getAudioInputStream(SoundP.class.getResource(folder + "/" + name));
}
clip.open(inputStream);
clip.start();
}while(clip.isActive());
inputStream.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
if語句僅適用於它們之后的第一個命令。 第二個'if'是無意義的,因為語句已經運行了。 它看起來像每次你循環播放剪輯是'.start'再次產生另一個線程,無論剪輯是否有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.