爲了防止無良網站的爬蟲抓取文章,特此標識,轉載請註明文章出處。LaplaceDemon/ShiJiaqi。html
http://www.cnblogs.com/shijiaqi1066/p/5976361.htmljava
Linux信號量是一種比較原始的進程通訊手段。有不少缺陷,可倒是理解操做系統的基礎概念。安全
使用 kill -l 查詢機器上全部信號量,不一樣操做系統上顯示的不同。多線程
一般Java只支持一種信號量的捕獲,即便用runtime.addShutdownHook()對退出信號作處理。ide
Runtime.getRuntime().addShutdownHook(handleThread); //handleThread是信號處理線程。
按照Java標準,Java不支持其餘信號的處理,由於這涉及到操做系統,而不是JVM層面的事情。但按照Java一向的尿性,不少看似沒辦法的特性均可以經過 sun.misc 包提供的一系列黑魔法來實現。網站
原則上sun.misc包中的內容不被推薦使用,因此編譯器會發出警告。須要添加 @SuppressWarnings("restriction") 來消除警告。spa
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佔用,USR一、USR2,能夠考慮用其它信號代替。
爲了防止無良網站的爬蟲抓取文章,特此標識,轉載請註明文章出處。LaplaceDemon/ShiJiaqi。