Java 如何从另一个方法停止/中断正在运行的线程?

Java 如何从另一个方法停止/中断正在运行的线程?,java,android,runnable,Java,Android,Runnable,我是android和Java开发的初学者,目前正在尝试制作节拍器。 在让声音播放正常工作后,我遇到的第一个问题是,每当节拍器播放时,应用程序就会停止响应——这就是我学习线程以及如何使用新线程进行音频播放的时候 创建一个新线程很有帮助,现在应用程序运行良好,但我无法让线程停止/中断。我已经读了大约50篇关于线程和中断的文章,但我想不出来 这是我的“Player”类代码,我主要是从另一篇堆栈溢出文章中复制的(我尝试了无数其他方法和变体,但都没有成功): 注意标有“?”的行。我自己添加了这个,因为“c

我是android和Java开发的初学者,目前正在尝试制作节拍器。 在让声音播放正常工作后,我遇到的第一个问题是,每当节拍器播放时,应用程序就会停止响应——这就是我学习线程以及如何使用新线程进行音频播放的时候

创建一个新线程很有帮助,现在应用程序运行良好,但我无法让线程停止/中断。我已经读了大约50篇关于线程和中断的文章,但我想不出来

这是我的“Player”类代码,我主要是从另一篇堆栈溢出文章中复制的(我尝试了无数其他方法和变体,但都没有成功):

注意标有“?”的行。我自己添加了这个,因为“catch(InterruptedException ex)”返回了一个错误。 以下是我的MainActivity类的相关代码:

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,if
m.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;
}