Java中處理Linux信號量


為了防止無良網站的爬蟲抓取文章,特此標識,轉載請注明文章出處。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。

http://www.cnblogs.com/shijiaqi1066/p/5976361.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM