轉帖|其它|編輯:郝浩|2010-12-29 15:09:27.000|閱讀 587 次
概述:本文將結合操作系統的信號機制,來嘗試實現一個簡單的,不依賴功能環境的Java異步通知功能。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
本文將結合操作系統的信號機制,來嘗試實現一個簡單的,不依賴功能環境的Java異步通知功能。
沒有特殊說明,本文所有的示例,都是基于Linux。
信號簡介
信號是在軟件層次上對中斷機制的一種模擬,在原理上,一個進程收到一個信號與處理器收到一個中斷請求可以說是一樣的。
通俗來講,信號就是進程間的一種異步通信機制。
典型的例子:
kill -s SIGKILL pid (即kill -9 pid) 立即殺死指定pid的進程。
在上面這個例子中,SIGKILL就是往pid進程發送的信號。
信號及其效果列表
//docs.google.com/View?id=dtbhrmv_754gh86rcg4
平臺相關性
信號具有平臺相關性,不同平臺下能使用的信號種類是有差異的。
在Linux下支持的信號(對比信號列表查看描述)
SEGV, ILL, FPE, BUS, SYS, CPU, FSZ, ABRT, INT, TERM, HUP, USR1, USR2, QUIT, BREAK, TRAP, PIPE
在Windows下支持的信號
SEGV, ILL, FPE, ABRT, INT, TERM, BREAK
信號選擇
為了不干擾正常信號的運作,又能模擬Java異步通知,我們需要先選定一種特殊的信號。
通過查看信號列表上的描述,發現 SIGUSR1 和 SIGUSR2 是允許用戶自定義的信號。
那么選擇它們,理論上就不會影響正常功能了。
這里我選用了USR2作為傳遞信號。原因是USR1有可能已被其他APP占用。
實例代碼
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* Java Signal Test
* @author Ken Wu
*
*/
@SuppressWarnings("restriction")
public class TestSignal implements SignalHandler {
private void signalCallback(Signal sn) {
System.out.println(sn.getName() + "is recevied.");
}
@Override
public void handle(Signal signalName) {
signalCallback(signalName);
}
public static void main(String[] args) throws InterruptedException {
TestSignal testSignalHandler = new TestSignal();
// install signals
Signal sig = new Signal("USR2");
Signal.handle(sig, testSignalHandler);
Thread.sleep(15000);
}
}
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* Java Signal Test
* @author Ken Wu
*
*/
@SuppressWarnings("restriction")
public class TestSignal implements SignalHandler {
private void signalCallback(Signal sn) {
System.out.println(sn.getName() + "is recevied.");
}
@Override
public void handle(Signal signalName) {
signalCallback(signalName);
}
public static void main(String[] args) throws InterruptedException {
TestSignal testSignalHandler = new TestSignal();
// install signals
Signal sig = new Signal("USR2");
Signal.handle(sig, testSignalHandler);
Thread.sleep(15000);
}
}
Sun為我們提供了2個方便安裝和替換信號處理器的工具類。
sun.misc.Signal
sun.misc.SignalHandler
將上面的代碼編譯后,運行,會暫停15秒,此時,是你給java進程發送信號最佳時機。
發送信號前,需要先通過 ps 或 jps 獲取java的進程id,然后運行
kill -s SIGUSR2 pid如果在java的stdout 看到 SIGUSR2 is recevied 字樣,說明信號被成功送達了。
在Java編程中使用信號的實際收益
信號作為最原始的進程間異步通信手段,有著諸多局限性的,比如不能傳遞上下文,信號隨時都可能被占用導致沖突,不具備擴展性等,所以對功能性需求來 說,使用它收益甚微。
當然,信號也不是一無是處,除了用作簡單的異步通知外,還可以利用它的進程事件通知功能。
在Java里有一個典型例子,就是 ShutdownHook。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載