如果程序关闭,Java如何停止线程

Posted

技术标签:

【中文标题】如果程序关闭,Java如何停止线程【英文标题】:Java how to stop thread if the program was closed 【发布时间】:2013-05-04 20:07:22 【问题描述】:

我遇到了一些异常,我需要知道程序何时自行关闭,因为我需要关闭套接字。

我有默认的公共静态 main 方法,我在其中不断重复一个动作和一个 Thread 类。

private static Thread thread;
public static boolean isRunning = true;  

public static void main(String[] args)

   thread = new Thread(new ThreadListenServer());
   thread.start();

   Timer timer = new Timer();
   TimerTask task = new TimerTask() 
      @Override
      public void run()
         // some action
      
   

   timer.scheduleAtFixedRate(task, 0, 10000);

   isRunning = false;

以及后台运行的线程类:

public class ThreadListenServer implements Runnable

    private DatagramSocket socket;

    public ThreadListenServer() throws SocketException
       socket = new DatagramSocket(6655);
    

    @Override
    public void run() 

       while(MainProgram.isRunning)
            // some action
       

       socket.close();
    

我不知道为什么,但isRunning 它正在变成假的,但它不应该。如果主程序已关闭,我应该如何关闭套接字? (这是因为即使程序关闭,线程仍然在后台运行)。

我正在考虑在主类中创建套接字,然后我将套接字对象作为参数传递给 ThreadClass,如果程序关闭,那么我也应该关闭套接字。

【问题讨论】:

当你关闭一个进程时,它会关闭它的所有资源,包括套接字。 它变成了假,因为你将它设置为假。 考虑使用执行器而不是单独的线程。完成后更容易重新获得控制权。 【参考方案1】:

用途:

thread.setDaemon(true);

这将关闭线程。它告诉JVM它是一个后台线程,所以它会在退出时关闭。

【讨论】:

【参考方案2】:

我假设您有一个作为 MainProgram 类运行的某种 JFrame。你有两个选择

1:设置你的Jframe在关闭时关闭所有线程。

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

2:添加一个窗口监听器并手动关闭你的线程(也许你必须在关闭它之前通过套接字发送一些信息)

addWindowListener(new WindowAdapter() 
  public void windowClosing(WindowEvent e) 
    // send your socket its close message and shut everything down
    System.exit(0);
  
);

【讨论】:

只有当所有 NON 守护线程都终止时,JVM 才会退出,这不会对 OPs 问题产生任何影响 查看documentation 以获得更好的描述 @MadProgrammer 我知道守护线程,但默认线程不是守护线程,我没有看到 OP 将它们设置为这样。还调用 System.exit 应该关闭所有这些线程。如果不是,那么选项 2 仍然可行(也是最好的 IMO)向所有线程发送关闭消息并关闭商店。 默认线程不是 DAEMON,当 JVM 存在时,OPs 线程不会被 JVM 自动终止,而是允许运行直到它自己存在。我也没有看到任何证据表明这与 swing 有任何关系,例如代码示例、cmets 或标签,所以充其量是评论,最坏的情况是猜测【参考方案3】:

要在您的程序干净退出时停止所有线程,您需要为每个启动的线程定义终止策略。这通常使用InterruptsExecutorService.shutdownNow() 方法来完成,向每个正在运行的线程发送一个中断。

干净的终止政策由两部分组成:

向线程发送停止信号——也就是中断它 设计线程以应对中断

调用Thread.interrupt() 方法可以中断Java 中的线程。线程可以通过调用Thread.isInterrupted() 方法来检查中断。一个好的线程必须定期检查中断,例如作为循环条件并检查 InterruptedExceptions 的阻塞函数。

需要注意的是,Java 中的Sockets 忽略了中断。例如,如果一个线程在Socket.accept() 上被阻塞,那么当线程被中断时它不会抛出InterruptedException。在这种情况下,您需要定义一个公共方法,通过调用Socket.close() 来关闭底层套接字,强制阻塞函数抛出异常(我猜是SocketException)。

【讨论】:

【参考方案4】:

我想到了一些事情。

    您似乎正在使用套接字执行阻塞 I/O 操作。您可能需要中断正在运行的线程和/或套接字以使其停止阻塞 您应该在启动前将线程设置为守护线程,使用setDaemon(true)。这将允许 JVM 自动终止线程... isRunning 应标记为 volatile 或者您应该改用 AtomicBoolean

【讨论】:

以上是关于如果程序关闭,Java如何停止线程的主要内容,如果未能解决你的问题,请参考以下文章

Java线程莫名停止

关闭 QT GUI 后如何停止线程

再次运行应用程序时如何停止关闭的应用程序留下的线程? C#

停止线程池的正确方法

如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]

如何正确停止线程