天天看点

基于OS信号实现Java异步通知

本文将结合操作系统的信号机制,来尝试实现一个简单的,不依赖功能环境的java异步通知功能。

没有特殊说明,本文所有的示例,都是基于linux。

信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

通俗来讲,信号就是进程间的一种异步通信机制。

典型的例子:

kill -s sigkill pid (即kill -9 pid) 立即杀死指定pid的进程。

在上面这个例子中,sigkill就是往pid进程发送的信号。

信号及其效果列表

<a href="http://docs.google.com/view?id=dtbhrmv_754gh86rcg4" target="_blank">http://docs.google.com/view?id=dtbhrmv_754gh86rcg4</a>

信号具有平台相关性,不同平台下能使用的信号种类是有差异的。

在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占用。

_/ java signal test @author ken wu_**

*/

@suppresswarnings(“restriction”)

public class testsignal implements signalhandler {

}

sun为我们提供了2个方便安装和替换信号处理器的工具类。

sun.misc.signal

sun.misc.signalhandler

将上面的代码编译后,运行,会暂停15秒,此时,是你给java进程发送信号最佳时机。

发送信号前,需要先通过 ps 或 jps 获取java的进程id,然后运行

如果在java的stdout 看到 sigusr2 is recevied 字样,说明信号被成功送达了。

信号作为最原始的进程间异步通信手段,有着诸多局限性的,比如不能传递上下文,信号随时都可能被占用导致冲突,不具备扩展性等,所以对功能性需求来说,使用它收益甚微。

当然,信号也不是一无是处,除了用作简单的异步通知外,还可以利用它的进程事件通知功能。

在java里有一个典型例子,就是 shutdownhook。

本文来源于"阿里中间件团队播客",原文发表时间" 2011-03-15"