多线程下Runtime.getRuntime().addShutdownHook(Thread) 的有效性讨论

diggywang 2009-04-17 10:48:38
代码如下,首先生成一个线程数组,如果数组小(3-5个),看起来执行正常,shutdownhook中定义的线程会在最后执行,但一旦线程数组加大,如100,200,则shutdownhook中定义的线程会在虚拟机没有退出前的最后一步执行,会在中间的某个时间点启动该线程。

请大家讨论一下原因,以及Runtime.getRuntime().addShutdownHook()的执行机理,是否和JDK文档中说的会在jvm退出前执行。

我的测试环境是Ubuntu 8.04, jdk1.5.0_17,jdk1.6.0_11


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
* @author qi
*/
public class SyncLockDemo2 {

public static void main(String[] xxx) {
Thread[] threads = new Thread[100];
final long t = System.nanoTime();
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run(){
System.err.println((System.nanoTime()-t)/1000000);
}
});
final byte[] lock1 = new byte[0];
final Lock lock2 = new ReentrantLock();
for (int i = 0; i < threads.length; i++) {
final int index = i;
Runnable run = new Runnable() {

public void run() {
synchronized (lock1) {
for (int k = 0; k < 1000; k++) {
System.out.println(index + ":" + k);
}
}
}
};
threads[i] = new Thread(run);
}
// for (int i = 0;
// i < threads.length;
// i++) {
// final int index = i;
// Runnable run = new Runnable() {
//
// public void run() {
// try {
// lock2.lock();
// for (int k = 0; k < 1000; k++) {
// System.out.println(index + ":" + k);
// }
// } finally {
// lock2.unlock();
// }
// }
// };
// threads[i] = new Thread(run);
//// threads[i].setDaemon(true);
// }
for (int i = 0;
i < threads.length;
i++) {
threads[i].start();
}

}
}
...全文
882 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
garid 2009-10-11
  • 打赏
  • 举报
回复
学习了 今天看Spring源代码才发现该方法,太落伍了。。。
javause 2009-04-18
  • 打赏
  • 举报
回复
一觉醒来,发觉自己原来是菜鸟中的菜鸟,学习了。
kingssman 2009-04-18
  • 打赏
  • 举报
回复
高人真多啊,学习了,呵呵。
qybao 2009-04-17
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 diggywang 的回复:]
晕,写的语无伦次了,CSDN还不允许修改。
/************************/
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是无法判断的?
[/Quote]

应该是无法判断的,管道输出是系统级别控制的(输出设备由系统管理),shutdownhook是jvm控制的,jvm的线程只管把数据传给管道,并不能保证管道一定要输出结束,如果非要控制,那就使用输出重定向,然后判断所有的数据都输出结束后再退出jvm
qybao 2009-04-17
  • 打赏
  • 举报
回复
我觉得这是输出管道缓存的问题
jvm退出时才执行hook,这点应该是没问题的
线程是通过out管道输出的,由于数量大时out管道不能及时处理过来,把数据都保存在缓存里
当所有的线程执行完后退出jvm,此时hook被调用,由于err只有少量数据,立刻被打印出来
JarodYv 2009-04-17
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 diggywang 的回复:]
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是无法判断的?
[/Quote]
可以这样理解。

shutdown hook仅仅是一个简单的被初始化但还没被启动的线程。当虚拟机启动关闭流程时,会启动所有注册了的shutdown hook,并且以只用不确定的次序执行这些shutdown hook线程。当所有shutdown hook线程都结束时,如果finalization-on-exit被设置为可用,虚拟机会执行所有为唤醒的finalizer。最后,虚拟机会被挂起。
goodmrning 2009-04-17
  • 打赏
  • 举报
回复
学习了!!!!!!!
MT502 2009-04-17
  • 打赏
  • 举报
回复
我觉得shutdownhook是可以判断的。
至于为什么会出现hook没有打印在最后,是因为不同的管道刷新时间的不确定造成的。
lhj_l 2009-04-17
  • 打赏
  • 举报
回复
学习了
diggywang 2009-04-17
  • 打赏
  • 举报
回复
晕,写的语无伦次了,CSDN还不允许修改。
/************************/
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是无法判断的?
diggywang 2009-04-17
  • 打赏
  • 举报
回复
err是我故意写的,就是为了测试不同管道处理的效果。
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是可以判断的还是无法判断的?
Dantin 2009-04-17
  • 打赏
  • 举报
回复
ls学习了,LZ用信号量试试
MT502 2009-04-17
  • 打赏
  • 举报
回复
那是因为你的程序写的不对,在hook里应该用System.out来输出
比如System.out.println("***"+(System.nanoTime()-t)/1000000);
这样不管你用多少个线程,hook都会在最后输出。
因为out和err是不同的流,线程少的时候结果正确仅仅是err缓冲在最后刷新的几率比较大而已。
ET郭强 2009-04-17
  • 打赏
  • 举报
回复
学习了,支持下

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧