Java 如何从另一个方法停止/中断正在运行的线程?
我是android和Java开发的初学者,目前正在尝试制作节拍器。 在让声音播放正常工作后,我遇到的第一个问题是,每当节拍器播放时,应用程序就会停止响应——这就是我学习线程以及如何使用新线程进行音频播放的时候 创建一个新线程很有帮助,现在应用程序运行良好,但我无法让线程停止/中断。我已经读了大约50篇关于线程和中断的文章,但我想不出来 这是我的“Player”类代码,我主要是从另一篇堆栈溢出文章中复制的(我尝试了无数其他方法和变体,但都没有成功): 注意标有“?”的行。我自己添加了这个,因为“catch(InterruptedException ex)”返回了一个错误。 以下是我的MainActivity类的相关代码:Java 如何从另一个方法停止/中断正在运行的线程?,java,android,runnable,Java,Android,Runnable,我是android和Java开发的初学者,目前正在尝试制作节拍器。 在让声音播放正常工作后,我遇到的第一个问题是,每当节拍器播放时,应用程序就会停止响应——这就是我学习线程以及如何使用新线程进行音频播放的时候 创建一个新线程很有帮助,现在应用程序运行良好,但我无法让线程停止/中断。我已经读了大约50篇关于线程和中断的文章,但我想不出来 这是我的“Player”类代码,我主要是从另一篇堆栈溢出文章中复制的(我尝试了无数其他方法和变体,但都没有成功): 注意标有“?”的行。我自己添加了这个,因为“c
public class MainActivity extends AppCompatActivity {
...
public Player p;
...
public void play() {
p = new Player();
p.start();
}
public void stop() {
p.stop();
}
}
调用p.stop();从方法内部来看,“stop”实际上什么都不做。这就是我被卡住的地方。如果在启动线程后立即调用p.stop(),如下所示:
public void play() {
p = new Player();
p.start();
p.stop();
}
然后它工作了,我看到了来自Player类的所有相关日志消息。当我从“stop”方法调用p.stop()时,为什么p.stop()不起作用?是因为我从另一个方法调用它,还是因为我没有立即调用它
任何帮助都将不胜感激,因为这非常令人沮丧。我一直在学习和实践Android开发,现在只有一个星期了,但在过去的5天里,我没有做任何事情,只是试图解决这个问题。谢谢你误解了中断的概念。中断并不是强迫线程停止的神奇方式,它只适用于支持中断的方法,比如睡眠 看看API,它列出了中断支持的方法: 如果此线程在调用
Objec
t类的wait()
、wait(long)
或wait(long,int)
方法或join()
、join(long)
、join(long,int)
、sleep(long)
、或sleep(long,int)
方法时被阻塞,然后,它的中断状态将被清除,并将收到一个中断异常
如果此线程在可中断的通道上的I/O操作中被阻塞,则通道将关闭,线程的中断状态将被设置,线程将收到一个closedbyinterrupexception
如果此线程在选择器中被阻塞,则线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样
如果前面的条件都不成立,则将设置该线程的中断状态。
通过不断地检查中断状态,您可以很好地使用中断支持实现自己的方法
现在让我们看看如何解决您的问题
根据您的评论,m.play()
不会返回,这意味着调用m.play()
后,while
不会检查线程是否中断;反过来,它将永远不会停止,因为m.play()
的实现不支持中断。这也应该解释为什么编译器抱怨没有人抛出中断异常
。(如果立即中断,它工作的原因是中断状态在到达之前发生了变化,而…想想看。)
现在,我假设,如果调用m.stop()
,m.play()
将返回,成功地重新检查线程中断。正如在评论中提到的,这就是它起作用的原因
但是你看,中断线程并没有什么实际意义——因为你所要做的就是调用m.stop()
并释放m.play()
,只需播放并等待返回——这意味着已经调用了stop。与循环相同,当循环时,将其完全放下
public void run() {
Log.i("a", "Thread starting.");
m.play(); // blocks till stopped from some other thread...
Log.i("b", "Thread stopping.");
Log.i("c", "Thread shutting down as it was requested to stop.");
backgroundThread = null;
}
在一种情况下,我可能会看到使用while
和interrupt,ifm.play()
返回的时间可能早于调用m.stop()
(例如,由于某些例外情况),并且您希望重新启动节拍器,直到调用stop为止;然后,一个循环可能处于rescue状态,中断可能通过调用m.stop()
发出信号,表明它实际上已停止
m.play()做什么?它会立即返回吗?m.play()不会立即返回,它是一个“while”循环。这与此有关吗?我需要打破这个循环吗?如果是这样的话,如果我在比赛结束后立即叫停怎么会起作用呢?我不敢相信,但它起了作用。。。我所做的就是在中断线程之前调用m.stop(节拍器停止函数)。我不知道我以前怎么没有做到这一点,尽管我在以前的尝试中确实尝试过。这整件事还是让我很困惑。。。谢谢你对我的回答的评论,请看一看。
public void run() {
Log.i("a", "Thread starting.");
m.play(); // blocks till stopped from some other thread...
Log.i("b", "Thread stopping.");
Log.i("c", "Thread shutting down as it was requested to stop.");
backgroundThread = null;
}
public void run() {
Log.i("a", "Thread starting.");
while (!backgroundThread.isInterrupted()) {
m.play();
if(!backgroundThread.isInterrupted())
Log.i("b", "Stopped by exception, restarting....");
}
Log.i("c", "Thread stopping.");
Log.i("d", "Thread shutting down as it was requested to stop.");
backgroundThread = null;
}