【问题标题】:Terminating all child threads on closing the stage/window在关闭阶段/窗口时终止所有子线程
【发布时间】:2013-09-12 05:40:19
【问题描述】:

我有多个已启动的子线程实例,应继续执行直到应用程序退出。

我有扩展 Task 的类,我将线程创建为

new Thread(object of the class).start();

所有线程都应该在主阶段关闭时终止。

primaryStage.onCloseOperation(){...}

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    我会从一开始就明确地管理您的线程。特别是,在您的父类中有一个线程池,如下所示:

    ExecutionService exec = Executors.newCachedExecutionService();
    

    那么,如果您的任务旨在继续运行(而不是定期安排),那么您的任务对中断的响应代码如下:

    while(!Thread.currentThread().isInterrupted()){
        do stuff;
    }
    

    这将使任务运行直到被中断。在这种情况下,重要的是永远不要忽略 InterruptedException,因为 InterruptedException 在抛出它们时将 isInterrupted 设置为 false。当您看到 InterruptedException 时执行此操作:

    }catch(InterruptedException e){
        Thread.currentThread().interrupt();
        return;
    }
    

    然后,您可以像这样开始您的子任务:

    for(task : tasks){
        exec.execute(task);
    }
    

    现在,当您的父任务完成时,您可以简单地调用:

    exec.shutdownNow();
    

    停止您的子任务。如果您的子任务使用Thread.currentThread().isInterrupted(),则必须使用shutdownNow()shutdown() 仅在您想等待任务自行停止时才有效)。

    【讨论】:

    • 如何使用 ExecutorService 创建新线程?或者自动创建的任何线程都属于 ExecutorService ?
    • @ItachiUchiha:啊抱歉忘了说如何开始任务。现在编辑进去了。线程将由执行器服务管理,是的。
    • 实际上我在不同的类中启动新线程,我应该将“exec”的引用传递给类的构造函数吗?或者这又是一个糟糕的设计?
    • @ItachiUchiha:那很好。
    【解决方案2】:

    您应该考虑使用ThreadGroup 对所有线程进行分组,然后控制它们的行为。 Java 5 在 java.lang.management 中添加了 ThreadInfo 和 ThreadMXBean 类来获取状态信息。

    这里有一个示例示例,可以使用此处提供的教程来实现此目的http://nadeausoftware.com/articles/2008/04/java_tip_how_list_and_find_threads_and_thread_groups

    获取所有线程的列表

    ThreadGroup 上的另一个 enumerate() 方法列出了该组的线程。使用真正的第二个参数,它将递归遍历组以使用 Thread 对象填充给定数组。从根 ThreadGroup 开始,您将获得 JVM 中所有线程的列表。

    这里的问题与列出线程组的问题相同。如果传递给 enumerate( ) 的数组太小,一些线程可能会从返回的数组中默默地删除。因此,您需要猜测数组大小,调用 enumerate(),检查返回值,如果数组已满,请重试。要获得一个好的开始猜测,请查看 java.lang.management 包。 ManagementFactory 类返回一个 ThreadMXBean,它的 getThreadCount() 方法返回 JVM 中的线程总数。当然,这可能会在稍后改变,但这是一个很好的初步猜测。

    Thread[] getAllThreads( ) {
        final ThreadGroup root = getRootThreadGroup( );
        final ThreadMXBean thbean = ManagementFactory.getThreadMXBean( );
        int nAlloc = thbean.getThreadCount( );
        int n = 0;
        Thread[] threads;
        do {
            nAlloc *= 2;
            threads = new Thread[ nAlloc ];
            n = root.enumerate( threads, true );
        } while ( n == nAlloc );
        return java.util.Arrays.copyOf( threads, n );
    }
    

    【讨论】:

      【解决方案3】:

      创建一个ExecutorService,它有一个ThreadFactory 来创建守护线程。

      例如:

      ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
           @Override
           public Thread newThread(Runnable r) {
              Thread thread = new Thread(r);
              thread.setDaemon(true);
              return thread;
           }
      });
      

      其余的如何使用它已经被@Enno 说了。

      谢谢恩诺 :)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-15
        • 2018-11-26
        • 1970-01-01
        • 2012-04-30
        相关资源
        最近更新 更多