轉載:
http://blog.csdn.net/wgw335363240/archive/2010/08/31/5854402.aspxRuntime.getRuntime().addShutdownHook(shutdownHook);
這個方法的含義說明:
這個方法的意思就是在jvm中增加一個關閉的鉤子,當jvm關閉的時候,會執(zhí)行系統(tǒng)中已經(jīng)設置的所有通過方法addShutdownHook添加的鉤子,當系統(tǒng)執(zhí)行完這些鉤子后,jvm才會關閉。所以這些鉤子可以在jvm關閉的時候進行內存清理、對象銷毀等操作。
調用方:- Runtime runtime = Runtime.getRuntime();
- EngineShutdownHook engineShutdownHook = new EngineShutdownHook();
- runtime.addShutdownHook(engineShutdownHook);
實現(xiàn):- public class EngineShutdownHook extends Thread {
- private static Logger logger = Logger.getLogger(EngineShutdownHook.class.getName());
-
- public void run() {
- JediLogger.debug(logger, "EngineShutdownHook - run] Entering method.");
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm:ss dd-MM-yyyy");
-
- Timestamp timestampStop = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampStop) + " - Stopping INFO Engine...");
- Engine.stop();
- Timestamp timestampStopped = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampStopped) + " - INFO Engine stopped.");
-
- Timestamp timestampDestroy = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampDestroy) + " - Destroying INFO Engine...");
- Engine.destroy();
-
- Timestamp timestampDestroyed = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampDestroyed) + " - INFO Engine destroyed.");
-
- Timestamp timestampComplete = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampComplete) + " - Shutdown complete");
-
- Timestamp timestampHalt = new Timestamp(new java.util.Date().getTime());
- System.out.println("[INFO] " + simpleDateFormat.format(timestampHalt) + " - Halting JVM");
- JediLogger.debug(logger, "com.prft.jedi.engine.EngineShutdownHook - run] Leaving method.");
- }
- }
測試類:
- public class RunTimeTest {
-
-
-
- public static void main(String[] args) {
- Thread thread1 = new Thread() {
- public void run() {
- System.out.println("thread1...");
- }
- };
-
- Thread thread2 = new Thread() {
- public void run() {
- System.out.println("thread2...");
- }
- };
-
- Thread shutdownThread = new Thread() {
- public void run() {
- System.out.println("shutdownThread...");
- }
- };
-
- Runtime.getRuntime().addShutdownHook(shutdownThread);
-
- thread1.start();
- thread2.start();
- }
- }
打印結果:
thread2...
thread1...
shutdownThread...
或者:
thread2...
thread1...
shutdownThread...
結論:
無論是先打印thread1還是thread2,shutdownThread 線程都是最后執(zhí)行的(因為這個線程是在jvm執(zhí)行關閉前才會執(zhí)行)。
- exec(String[] cmdarray, String[] envp, File dir)
Executes the specified command and arguments in a separate process with the specified environment and working directory.
那個dir就是調用的程序的工作目錄,這句其實還是很有用的。
Windows下調用程序
- Process proc =Runtime.getRuntime().exec("exefile");
Linux下調用程序就要改成下面的格式
- Process proc =Runtime.getRuntime().exec("./exefile");
Windows下調用系統(tǒng)命令
- String [] cmd={"cmd","/C","copy exe1 exe2"};
- Process proc =Runtime.getRuntime().exec(cmd);
Linux下調用系統(tǒng)命令就要改成下面的格式
- String [] cmd={"/bin/sh","-c","ln -s exe1 exe2"};
- Process proc =Runtime.getRuntime().exec(cmd);
Windows下調用系統(tǒng)命令并彈出命令行窗口
- String [] cmd={"cmd","/C","start copy exe1 exe2"};
- Process proc =Runtime.getRuntime().exec(cmd);
Linux下調用系統(tǒng)命令并彈出終端窗口就要改成下面的格式
- String [] cmd={"/bin/sh","-c","xterm -e ln -s exe1 exe2"};
- Process proc =Runtime.getRuntime().exec(cmd);
還有要設置調用程序的工作目錄就要
- Process proc =Runtime.getRuntime().exec("exeflie",null, new File("workpath"));
當然最好的執(zhí)行系統(tǒng)命令的方法就是寫個bat文件或是shell腳本。然后調用,那樣修改和實現(xiàn)就簡點多了。
用Java編寫應用時,有時需要在程序中調用另一個現(xiàn)成的可執(zhí)行程序或系統(tǒng)命令,這時可以通過組合使用Java提供的Runtime類和Process類的方法實現(xiàn)。
下面是一種比較典型的程序模式:
- Process process = Runtime.getRuntime().exec("p.exe");
- process.waitfor( );
在上面的程序中,第一行的“p.exe”是要執(zhí)行的程序名,Runtime.getRuntime()返回當前應用程序的Runtime對象,該對象的 exec()方法指示Java虛擬機創(chuàng)建一個子進程執(zhí)行指定的可執(zhí)行程序,并返回與該子進程對應的Process對象實例。通過Process可以控制該子進程的執(zhí)行或獲取該子進程的信息。第二條語句的目的等待子進程完成再往下執(zhí)行。 但在windows平臺上,如果處理不當,有時并不能得到預期的結果。下面是筆者在實際編程中總結的幾種需要注意的情況:
1、執(zhí)行DOS的內部命令 如果要執(zhí)行一條DOS內部命令,有兩種方法。一種方法是把命令解釋器包含在exec()的參數(shù)中。
例如,執(zhí)行dir命令,在 NT上,可寫成exec ("cmd.exe /c dir"),在windows 95/98下,可寫成“command.exe /c dir”,其中參數(shù)“/c”表示命令執(zhí)行后關閉Dos立即關閉窗口。另一種方法是,把內部命令放在一個批命令my_dir.bat文件中,在Java程序中寫成exec("my_dir.bat")。如果僅僅寫成exec("dir"),Java虛擬機則會報運行時錯誤。前一種方法要保證程序的可移植性,需要在程序中讀取運行的操作系統(tǒng)平臺,以調用不同的命令解釋器。后一種方法則不需要做更多的處理。
2、打開一個不可執(zhí)行的文件 打開一個不可執(zhí)行的文件,但該文件存在關聯(lián)的應用程序,則可以有兩種方式。 以打開一個word文檔a.doc文件為例,Java中可以有以下兩種寫法:
- exec("start a.doc");
- exec(" c:\\Program Files\\Microsoft Office\\office winword.exe a.doc");
顯然,前一種方法更為簡捷方便。
3、執(zhí)行一個有標準輸出的DOS可執(zhí)行程序 在windows 平臺上,運行被調用程序的DOS窗口在程序執(zhí)行完畢后往往并不會自動關閉,從而導致Java應用程序阻塞在waitfor( )。導致該現(xiàn)象的一個可能的原因是,該可執(zhí)行程序的標準輸出比較多,而運行窗口的標準輸出緩沖區(qū)不夠大。解決的辦法是,利用Java提供的Process 類提供的方法讓Java虛擬機截獲被調用程序的DOS運行窗口的標準輸出,在waitfor()命令之前讀出窗口的標準輸出緩沖區(qū)中的內容。一段典型的程序如下:
- String str;
- Process process = Runtime.getRuntime().exec("cmd /c dir windows");
- BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(process.getInputStream());
- while ( (str=bufferedReader.readLine()) != null) System.out.println(str);
- process.waitfor();