困扰已久的俩个问题:线程执行超时的控制和怎么判断对象是否可以回收内存
困扰已久的俩个问题:希望大牛们排扰解难,非常感谢!第一个:程执行超时的控制,像我们在eclipse里面启动tomcat,如果时间太长,会报Server Tomcat v6.0 Server at Tomcat6.0 was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor. 这个错误是时间设太短导致的,我
想问一下这样的一个线程监控是怎么实现的,超过45S就自动中止了?线程的stop方法不建议使用,也实现不了这样的情况,而interrupt方法又不能中断正在运行的程序,我把tomcat的源码弄下来看了一下,也没有找到相关的代码,哪位帮助实现一下,或者源码也行。
第二个:怎么判断对象是否可以回收内存,对象没有被引用了就可以被回收了,我想知道用代码怎么来测试它是否可以被回收(或没有被引用了),JVM又是怎么判断的? 线程超时 回收内存 tomcat 启动 --------------------编程问答-------------------- 那个超时和你这里线程不是一个概念。你说线程的超时应该是执行时间吧。线程调用了start方法就启动了。
第二个问题我只是理论上知道原理,没去深究,回去研究下 --------------------编程问答-------------------- 第一个问题,搜了把,感觉这个挺靠谱的:http://tech.sina.com.cn/s/2008-07-04/1051720260.shtml
第二个问题,个人一些不成熟的理解,欢迎纠正:可回收的对象,这个概念就是没有指向这个对象的引用。假设存在一个测试方法来监控这个对象,那这个测试方法应该存在一个引用。这样就与产生一个矛盾了。虚拟机应该是通过<索引,内存地址>这样一个关系来管理内存的,当一个内存地址,没有任何一个索引指向它时,就可以被回收了。
欢迎纠正 --------------------编程问答-------------------- --------------------编程问答--------------------
关于线程超时的问题,其实timer也是另外启动一个线程去监听时间,那么如果每个线程都加一个timer,那么实际的线程数就变成原来的2倍,这样是不是很耗性能啊?有没有别的方式实现超时控制呢? --------------------编程问答--------------------
程序执行是串行的话,只有运行结束了才知道时间。想要在程序还未结束就计算超时,总需要有第三方来监控。 --------------------编程问答-------------------- 第二个问题。可以读读这个文章,虽然不知道从哪转来的:http://blog.csdn.net/originalcsdn/article/details/6269630 --------------------编程问答-------------------- 针对第二个问题:我敢肯定的是正常情况下,只要把对象引用设置为null,GC就会回收内存。 --------------------编程问答-------------------- 第一个问题, elcipse启动tomcat,tomcat不是作为JVM线程被启动。
tomcat是当作OS进程被启动的。
Linux的话,该进程是eclipse进程的子进程。
eclipse在启动“tomcat start”个Process的时候,另外启动一个计时线程,该线程sleep 45秒,等该线程醒来时,判断Process是否已返回,若未返回则报错。
第二个问题,在java里是干不了了。你得Hack JVM,
某些JVM是开源的,你可以拿来改,大部分JVM都是C/C++写的。 --------------------编程问答--------------------
第一个问题,搜了把,感觉这个挺靠谱的:http://tech.sina.com.cn/s/2008-07-04/1051720260.shtml
第二个问题,个人一些不成熟的理解,欢迎纠正:可回收的对象,这个概念就是没有指向这个对象的引用。假设存在一个测试方法来监控这个对象,那这个测试方法应该存在一个引用。这样就与产生一个矛盾了。虚拟机应该是通过<索引,内存地址>这样一个关系来管理内存的,当一个内存地址,没有任何一个索引指向它时,就可以被回收了。
欢迎纠正
感谢回复, 第一问题的这个解决办法我试过的,这个异常是捕捉不到的。 --------------------编程问答--------------------
第一个问题, elcipse启动tomcat,tomcat不是作为JVM线程被启动。
tomcat是当作OS进程被启动的。
Linux的话,该进程是eclipse进程的子进程。
eclipse在启动“tomcat start”个Process的时候,另外启动一个计时线程,该线程sleep 45秒,等该线程醒来时,判断Process是否已返回,若未返回则报错。
第二个问题,在java里是干不了了。你得Hack JVM,
某些JVM是开源的,你可以拿来改,大部分JVM都是C/C++写的。
beowulf2005兄:能说更详细一点吗?像第一个,判断Process是否已返回,若未返回则报错,是怎样个原理,就是抛异常?服务又是怎样停的?相当于KILL掉了吗?
第二个问题:你有做过吗?能举个例子不?
--------------------编程问答-------------------- 第一个,
自己看下 process 文档
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
destory的时候应该就算Kill,但有时候普通的kill信号kill不掉,还得自己kill -9
第二个,简单看过下文档,玩一下,没用它干过实际工作。一般也用不到就是了。
http://docs.oracle.com/javase/7/docs/technotes/guides/jvmti/
主要用来写Agent,基本上能监听到JVM的各种动作,JVM GC回收Object前,会发出ObjectFree事件。
你标注你关心的Object,然后Agent监听它,就知道那些Object什么时候被Free了。
另外写javaagent就已经可以满足通常监控的需要了。javaagent是java写的,比较容易写。
http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html
--------------------编程问答--------------------
第一个问题,搜了把,感觉这个挺靠谱的:http://tech.sina.com.cn/s/2008-07-04/1051720260.shtml
第二个问题,个人一些不成熟的理解,欢迎纠正:可回收的对象,这个概念就是没有指向这个对象的引用。假设存在一个测试方法来监控这个对象,那这个测试方法应该存在一个引用。这样就与产生一个矛盾了。虚拟机应该是通过<索引,内存地址>这样一个关系来管理内存的,当一个内存地址,没有任何一个索引指向它时,就可以被回收了。
欢迎纠正
感谢回复, 第一问题的这个解决办法我试过的,这个异常是捕捉不到的。
你说的对,确实捕捉不到。后来查阅了些资料,似乎没什么好办法直接中断一个线程。
后来考虑到事件的原子性,做了个demo,就是一个任务分成多个事件,每个事件执行前判断下是否超时,以此来判断是否需要继续执行下去。源码如下:
--------------------编程问答-------------------- 超时的问题我试了一下Timer和TimerTast,是可以实现的,不过还没有研究它是怎么实现的,里面好像还有JVM的命令,有谁知道原理的请分享一下,多谢。 --------------------编程问答-------------------- 关于线程超时,楼主可以看看future 这个可以做类似于线程超时就返回的需求
public class TestTimeout {
public static void main(String[] args) {
new Thread(new OneRun()).start();
}
}
// 自定义线程
class OneRun implements Runnable {
// 超时标记
private boolean timeoutFLG = false;
public synchronized void setTimoutFLG(boolean 易做图) {
timeoutFLG = 易做图;
}
@Override
public void run() {
// 将多个原子操作间,通过超时标记判断是否超时
int num = 0;
System.out.println("我要做20件事情.");
// 初始化一个监控线程来监控自己是否超时.时间设置为10秒
TimeoutThread timeoutThread = new TimeoutThread(this, 10000);
timeoutThread.start();
try {
while (!timeoutFLG && num++ < 20) {
System.out.println("第" + num + "件事情开始...");
// 每件时间耗时1秒
Thread.sleep(1000);
System.out.println("第" + num + "件事情结束.");
}
// 判断是否是正常结束
if (timeoutFLG) {
System.out.println("事情没做完啊,兄弟你超时了...");
return;
}
System.out.println("事情都搞定了!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("花了10秒钟.");
}
}
// 超时监控类
class TimeoutThread extends Thread {
// 计时器超时时间
private long timeout;
private OneRun oneRun;
public TimeoutThread(OneRun oneRun, long timeout) {
this.oneRun = oneRun;
this.timeout = timeout;
}
@Override
public void run() {
try {
System.out.println("---TimeoutThread.run---");
System.out.println("---begin sleep---");
// 超时了就设置超时标记
Thread.sleep(timeout);
oneRun.setTimoutFLG(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
另外对象回收,那是JVM的事情, 什么时候回收,怎么回收。。这也不可控啊。 --------------------编程问答-------------------- 天哪太恐怖了 --------------------编程问答--------------------
超时的问题我试了一下Timer和TimerTast,是可以实现的,不过还没有研究它是怎么实现的,里面好像还有JVM的命令,有谁知道原理的请分享一下,多谢。
Timer 是JDK实现的一步分,源码不复杂,在你的JDK安装路径下就可以找到。
除了里面用到AtomicInteger之外,没有底层的东西。(AtomicInteger里有native方法封装了CPU指令)
java 线程模型是合作式线程模型。和Linux,Win等OS的竞争式进程管理模型不一样。
你在java里无法剥夺java线程的资源,除非他主动让出。
这些大学应该都教过啊。 --------------------编程问答--------------------
第一个问题,搜了把,感觉这个挺靠谱的:http://tech.sina.com.cn/s/2008-07-04/1051720260.shtml
第二个问题,个人一些不成熟的理解,欢迎纠正:可回收的对象,这个概念就是没有指向这个对象的引用。假设存在一个测试方法来监控这个对象,那这个测试方法应该存在一个引用。这样就与产生一个矛盾了。虚拟机应该是通过<索引,内存地址>这样一个关系来管理内存的,当一个内存地址,没有任何一个索引指向它时,就可以被回收了。
欢迎纠正
感谢回复, 第一问题的这个解决办法我试过的,这个异常是捕捉不到的。
你说的对,确实捕捉不到。后来查阅了些资料,似乎没什么好办法直接中断一个线程。
后来考虑到事件的原子性,做了个demo,就是一个任务分成多个事件,每个事件执行前判断下是否超时,以此来判断是否需要继续执行下去。源码如下:
public class TestTimeout {
public static void main(String[] args) {
new Thread(new OneRun()).start();
}
}
// 自定义线程
class OneRun implements Runnable {
// 超时标记
private boolean timeoutFLG = false;
public synchronized void setTimoutFLG(boolean 易做图) {
timeoutFLG = 易做图;
}
@Override
public void run() {
// 将多个原子操作间,通过超时标记判断是否超时
int num = 0;
System.out.println("我要做20件事情.");
// 初始化一个监控线程来监控自己是否超时.时间设置为10秒
TimeoutThread timeoutThread = new TimeoutThread(this, 10000);
timeoutThread.start();
try {
while (!timeoutFLG && num++ < 20) {
System.out.println("第" + num + "件事情开始...");
// 每件时间耗时1秒
Thread.sleep(1000);
System.out.println("第" + num + "件事情结束.");
}
// 判断是否是正常结束
if (timeoutFLG) {
System.out.println("事情没做完啊,兄弟你超时了...");
return;
}
System.out.println("事情都搞定了!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("花了10秒钟.");
}
}
// 超时监控类
class TimeoutThread extends Thread {
// 计时器超时时间
private long timeout;
private OneRun oneRun;
public TimeoutThread(OneRun oneRun, long timeout) {
this.oneRun = oneRun;
this.timeout = timeout;
}
@Override
public void run() {
try {
System.out.println("---TimeoutThread.run---");
System.out.println("---begin sleep---");
// 超时了就设置超时标记
Thread.sleep(timeout);
oneRun.setTimoutFLG(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这种方式是自己停止,我也想到过,如果被分成的小事情还是很慢,或卡死,线程中止不了了。
可能真还要从操作系统的线程来处理了。 --------------------编程问答-------------------- 第一个实现可能的方式。起一个线程。
run(){
while(启动没结束){
if(超时){
// log
System.exit(0); // 结束jvm
}
}
// 启动完毕,结束线程。
}
补充:Java , Java EE