为了账号安全,请及时绑定邮箱和手机立即绑定

来自不同函数的线程中断

来自不同函数的线程中断

阿波罗的战车 2021-12-10 10:02:40
我目前正在启动一个新线程并试图从另一个函数中中断它。像这样public static void simulate(ActionEvent e){ //Runs the Simulation in a new thread, allowing for realtime updating of the Textarea    Simulate simulation = new Simulate(0.1, Main.house);    Thread simThread = new Thread(simulation.simulate()) {};    simThread.start();}public static void pause(ActionEvent e){    simThread.interrupt();}但是,暂停内的 simThread 当然是未定义的。我试图在函数之外提取模拟和 simThread 的初始化并将它们公开。但这导致尝试启动 simThread 时出现空指针异常。任何有关如何跨函数共享线程或如何解决此问题的帮助将不胜感激。
查看完整描述

2 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

提供的代码中有很多错误,我必须提前几步才能正确回答问题。


1. 您使用的是哪个线程构造函数?


Thread 提供了几种构造函数,它们将字符串、Runnable 或线程组作为参数。您的函数构造线程,其结果simulation.simulate()必须是上述返回类型之一才能编译。我很确定您没有意识到此时整个simulate函数正在运行并在线程启动之前完成。另请注意,您随后定义了具有空实现 (the { })的抽象 Thread 类。


尝试像这样初始化线程:


final Simulate simulation = new Simulate(0.1, Main.house);

Thread simThread = new Thread(simulation::simulate);

这会将方法simulate本身作为Runnable参数传递给 Thread 构造函数。请注意,要使其工作,模拟方法必须是 return-type void。


2. 外部函数应该如何访问局部变量?


在您的方法中,您声明了一个仅对方法本身可见的变量。任何外部代码应该如何解决它?您至少需要返回局部变量(因此将其公开):


public static Thread simulate(ActionEvent e){

  final Simulate simulation = new Simulate(0.1, Main.house);

  final Thread simThread = new Thread(simulation::simulate);

  simThread.start();

  return simThread;

}

现在外部调用者将接收已创建的线程,然后可以中断它 theReturnedValue.interrupt()


或者,您可以将 id 分配给您创建的线程并在内部管理它们,但这超出了本答案的范围。


3. 你认为interrupt是什么?


没有(合法的)方法可以阻止线程运行,因此唯一interrupt能做的就是向线程发送“请求”以停止工作。由于您还没有发布simulate方法,我只能猜测那里会发生什么。


interrupt将导致所有阻塞操作突然继续并在当前线程上设置中断标志,这通常会导致InterruptedException抛出an 。您可以对此做出反应或检查Thread.interrupted方法,如果调用该函数的线程的中断标志已被某人设置(这应该是您在您的情况下创建的线程),则该方法将返回 true 。


进一步阅读


对于您的情况,FutureTask已被折叠并应使用。它需要一个Executor来运行实际任务。


查看完整回答
反对 回复 2021-12-10
?
青春有我

TA贡献1784条经验 获得超8个赞

如果你能编译这段代码,我假设你已经在某处声明了一个simThread静态变量。


显然,您可以simulate通过不重新声明来初始化该静态变量:


public static void simulate(ActionEvent e){ //Runs the Simulation in a new thread, allowing for realtime updating of the Textarea

    Simulate simulation = new Simulate(0.1, Main.house);

    simThread = new Thread(simulation.simulate()) {};

    simThread.start();


}

但您必须确保:


simulate总是在之前被调用pause,并且

simulate没有pause中间没有被调用两次。

您可以像这样确保这些条件:


public static synchronized void simulate(ActionEvent e){ //Runs the Simulation in a new thread, allowing for realtime updating of the Textarea

    if (simThread != null) {

        throw new IllegalStateException("A simulation is already running.");

    }

    Simulate simulation = new Simulate(0.1, Main.house);

    simThread = new Thread(simulation.simulate()) {};

    simThread.start();

}


public static synchronized void pause(ActionEvent e){

    if (simThread == null) {

        throw new IllegalStateException("Simulation is not running.");

    }

    simThread.interrupt();

    simThread = null;

}


查看完整回答
反对 回复 2021-12-10
  • 2 回答
  • 0 关注
  • 163 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信