Java 关闭阶段/窗口时终止所有子线程
我有多个子线程实例,这些子线程已启动,并应继续在中执行,直到应用程序退出 我有扩展任务的类,我创建线程作为Java 关闭阶段/窗口时终止所有子线程,java,multithreading,javafx,Java,Multithreading,Javafx,我有多个子线程实例,这些子线程已启动,并应继续在中执行,直到应用程序退出 我有扩展任务的类,我创建线程作为 new Thread(object of the class).start(); 所有线程都应在主阶段关闭时终止 primaryStage.onCloseOperation(){...} 您应该考虑使用ThreadGroup对所有线程进行分组,然后控制它们的行为。Java5在Java.lang.management中添加了ThreadInfo和ThreadMXBean类以获取状态信息
new Thread(object of the class).start();
所有线程都应在主阶段关闭时终止
primaryStage.onCloseOperation(){...}
您应该考虑使用
ThreadGroup
对所有线程进行分组,然后控制它们的行为。Java5在Java.lang.management中添加了ThreadInfo和ThreadMXBean类以获取状态信息
以下是使用此处提供的教程实现此目的的示例:
获取所有线程的列表
ThreadGroup上的另一个enumerate()方法列出该组的线程。如果第二个参数为true,它将递归地遍历组,用线程对象填充给定数组。从根线程组开始,您将获得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 );
}
您应该考虑使用
ThreadGroup
对所有线程进行分组,然后控制它们的行为。Java5在Java.lang.management中添加了ThreadInfo和ThreadMXBean类以获取状态信息
以下是使用此处提供的教程实现此目的的示例:
获取所有线程的列表
ThreadGroup上的另一个enumerate()方法列出该组的线程。如果第二个参数为true,它将递归地遍历组,用线程对象填充给定数组。从根线程组开始,您将获得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 );
}
我会从一开始就明确地管理你的线程。特别是,在父类中有一个线程池,如下所示:
ExecutionService exec = Executors.newCachedExecutionService();
for(task : tasks){
exec.execute(task);
}
然后,如果您的任务要保持运行(而不是定期安排),请将您的任务编码为响应中断,如下所示:
while(!Thread.currentThread().isInterrupted()){
do stuff;
}
这将使任务一直运行到中断。在这种情况下,切勿忽略InterruptedException
,因为InterruptedException
在抛出时将isInterrupted
设置为false,这一点很重要。当您看到中断异常时执行此操作:
}catch(InterruptedException e){
Thread.currentThread().interrupt();
return;
}
然后,您可以启动子任务,如下所示:
ExecutionService exec = Executors.newCachedExecutionService();
for(task : tasks){
exec.execute(task);
}
现在,当父任务完成时,您只需调用:
exec.shutdownNow();
停止您的子任务。如果您的子任务使用Thread.currentThread().isInterrupted()
,则必须使用shutdownNow()
(shutdown()
仅在您希望等待任务自行停止时有效) 我会从一开始就明确地管理您的线程。特别是,在父类中有一个线程池,如下所示:
ExecutionService exec = Executors.newCachedExecutionService();
for(task : tasks){
exec.execute(task);
}
然后,如果您的任务要保持运行(而不是定期安排),请将您的任务编码为响应中断,如下所示:
while(!Thread.currentThread().isInterrupted()){
do stuff;
}
这将使任务一直运行到中断。在这种情况下,切勿忽略InterruptedException
,因为InterruptedException
在抛出时将isInterrupted
设置为false,这一点很重要。当您看到中断异常时执行此操作:
}catch(InterruptedException e){
Thread.currentThread().interrupt();
return;
}
然后,您可以启动子任务,如下所示:
ExecutionService exec = Executors.newCachedExecutionService();
for(task : tasks){
exec.execute(task);
}
现在,当父任务完成时,您只需调用:
exec.shutdownNow();
停止您的子任务。如果您的子任务使用Thread.currentThread().isInterrupted()
,则必须使用shutdownNow()
(shutdown()
仅在您希望等待任务自行停止时有效) 创建一个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已经说过了
谢谢Enno:)创建一个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已经说过了
谢谢Enno:)如何使用ExecutorService创建新线程?或者任何自动创建的线程都属于ExecutorService?@ItachiUchiha:啊,对不起,忘了提到如何启动任务。现在编辑它。线程将由executor服务管理,是的。实际上我在不同的类中启动了新线程,我是否应该将“exec”的引用传递给类的构造函数?或者这又是一个糟糕的设计?@ItachiUchiha:那很好。我如何使用ExecutorService创建新线程?或者任何自动创建的线程都属于ExecutorService?@ItachiUchiha:啊,对不起,忘了提到如何启动任务。现在编辑它。线程将由executor服务管理,是的。实际上我在不同的类中启动了新线程,我是否应该将“exec”的引用传递给类的构造函数?否则这又是一个糟糕的设计