代码如下,首先生成一个线程数组,如果数组小(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();
} }
}
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();
} }
}
比如System.out.println("***"+(System.nanoTime()-t)/1000000);
这样不管你用多少个线程,hook都会在最后输出。
因为out和err是不同的流,线程少的时候结果正确仅仅是err缓冲在最后刷新的几率比较大而已。
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是可以判断的还是无法判断的?
/************************/
是否我可以这样理解:多个线程在处理系统管道的事情的时候,shutdownhook是无法判断的?
至于为什么会出现hook没有打印在最后,是因为不同的管道刷新时间的不确定造成的。
jvm退出时才执行hook,这点应该是没问题的
线程是通过out管道输出的,由于数量大时out管道不能及时处理过来,把数据都保存在缓存里
当所有的线程执行完后退出jvm,此时hook被调用,由于err只有少量数据,立刻被打印出来
应该是无法判断的,管道输出是系统级别控制的(输出设备由系统管理),shutdownhook是jvm控制的,jvm的线程只管把数据传给管道,并不能保证管道一定要输出结束,如果非要控制,那就使用输出重定向,然后判断所有的数据都输出结束后再退出jvm