我有许多执行长期任务的线程。这些线程本身具有子线程,可以进一步细分工作。跟踪以下内容的最佳方式是什么:
我想以尽可能高效的方式做到这一点,一旦线程完成,我不希望任何引用它们,因为我需要尽早释放内存。
有什么建议吗?
答案 0 :(得分:4)
不要考虑线程,它是OS对象并且不带任何应用程序语义,而是考虑任务。一个线程不能知道它完成了50%,任务就可以了。查看java.util.concurrent中的工具,以便根据执行程序和可调用对象管理任务。
在大多数使用Java的情况下(即非嵌入式系统),你不应该关心你的进程创建了多少线程(或者更少)而不是它创建了多少个对象 - 你不需要要用完,但如果你用高级语言显式管理操作系统资源,你可能会在错误的抽象层次上工作。
对于中间反馈,创建一个进度监听器接口,其中包含一个方法,用于通知监听器任务所在的位置,在创建时将其传递给任务,并在进度发生变化时在任务期间调用它。确保接口的任何实现都是线程安全的。
答案 1 :(得分:1)
您正在寻找的信息似乎主要是针对特定应用的(“每个线程当前执行的流程的哪一部分?”)。甚至,“我的进程创建了多少总线程数”也是特定于应用程序的,因为您对JVM创建的所有类型的线程(GUI,GC等)都不感兴趣。
因此,最好的做法是创建Thread的专用子类。线程开始/完成处理作业的内容您的类将使用某个中央注册表注册必要的详细信息。
[编辑]
这是一个典型的实现(可以进一步细化):
public class MyThread extends Thread
{
private Runnable runnable;
private String description;
private Registry reg;
public MyThread(Runnable runnable, String description, Registry reg) {
this.runnable = runnable;
this.description = description;
this.reg = reg;
}
public void run() {
int id = reg.jobStarting(description);
try {
runnable.run();
reg.jobEnded(id);
}
catch(Throwable t) {
reg.jobFailed(id, t);
}
}
}
答案 2 :(得分:0)
使用JMX:http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html
将以下参数添加到您的jvm(javac
...之后):
-Dcom.sun.management.jmxremote.port=8086 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
然后使用jconsole
进行连接。 JConsole将位于JDK的bin文件夹中。我确信它带有JDK,但我不确定它是否与JRE捆绑在一起。在这种情况下,当JConsole弹出时,输入localhost:8086
作为IP地址。如果需要,请更改端口。
在JConsole中,单击Thread
选项卡。这将显示带有漂亮图形的运行和启动线程的数量。您还可以单击该线程以查看当前堆栈跟踪。你甚至有一个按钮来检测死锁!
答案 3 :(得分:0)
我会完全改变设计方法,并使用Work
代替Threads
原因。
将您的大任务分为work
,并将其提交给执行者/工作者(另请参阅线程池模式)。然后,您可以注册listener
,以便在工作开始/完成/中止时收到通知。
JCA规范在WorkManager中实现了这种模式,你可以从中得到一些灵感:
void scheduleWork(Work work,
long startTimeout,
ExecutionContext execContext,
WorkListener workListener)
和听众
void workAccepted(WorkEvent e);
void workCompleted(WorkEvent e);
void workRejected(WorkEvent e);
void workStarted(WorkEvent e);
否则看看java.util.concurrent
还有一些有趣的东西。
答案 4 :(得分:0)
使用sun / oracle中的Visual VM,免费工具。非常好的工具,为您提供有关线程,使用的内存,运行进程的CPU的大量详细信息。