為了防止無良網站的爬蟲抓取文章,特此標識,轉載請注明文章出處。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/5976361.html
Linux信號量
Linux信號量是一種比較原始的進程通信手段。有很多缺陷,可卻是理解操作系統的基礎概念。
使用 kill -l 查詢機器上所有信號量,不同操作系統上顯示的不一樣。
Java中處理信號量
通常Java只支持一種信號量的捕獲,即使用runtime.addShutdownHook()對退出信號做處理。
Runtime.getRuntime().addShutdownHook(handleThread); //handleThread是信號處理線程。
按照Java標准,Java不支持其他信號的處理,因為這涉及到操作系統,而不是JVM層面的事情。但按照Java一貫的尿性,很多看似沒辦法的特性都可以通過 sun.misc 包提供的一系列黑魔法來實現。
原則上sun.misc包中的內容不被推薦使用,所以編譯器會發出警告。需要添加 @SuppressWarnings("restriction") 來消除警告。
package sjq.signal.java; import sun.misc.Signal; import sun.misc.SignalHandler; @SuppressWarnings("restriction") public class SignalTest { public static void main(String[] args) throws InterruptedException { // 信號處理實例 MySignalHandler mySignalHandler = new MySignalHandler(); // 注冊對指定信號的處理 Signal.handle(new Signal("TERM") ,mySignalHandler); // kill or kill -15 Signal.handle(new Signal("INT"), mySignalHandler); // kill -2 System.out.println("[Thread:"+Thread.currentThread().getName() + "] is sleep" ); while(true) Thread.sleep(1000); } } @SuppressWarnings("restriction") class MySignalHandler implements SignalHandler { @Override public void handle(Signal signal) { // 信號量名稱 String name = signal.getName(); // 信號量數值 int number = signal.getNumber(); // 當前進程名 String currentThreadName = Thread.currentThread().getName(); System.out.println("[Thread:"+currentThreadName + "] receved signal: " + name + " == kill -" + number); if(name.equals("TERM")){ System.exit(0); } } }
在命令行中輸入多個kill -2和一個kill后,打印如下內容:
[Thread:main] is sleep [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGINT handler] receved signal: INT == kill -2 [Thread:SIGTERM handler] receved signal: TERM == kill -15
可以看出Java對每個信號都啟動一個線程進行處理。注冊TERM信號,就啟動"SIGTERM handler" 線程。即便主線程被阻塞,信號依然可以得到處理。
由於對信號的處理是多線程的,所以應保證信號處理實例SignalHandler應該是線程安全的。
對於某些信號運行中可能會拋出異常:
java.lang.IllegalArgumentException: Signal already used by VM: USR1
這是因為某些信號可能已經被JVM占用,USR1、USR2,可以考慮用其它信號代替。
為了防止無良網站的爬蟲抓取文章,特此標識,轉載請注明文章出處。LaplaceDemon/ShiJiaqi。