[英]How do I write native code which responds to `Thread.interrupt()`?
在Java中,所有标准的阻塞方法都可以通过调用Thread.interrupt()
来中断,但是如果我们有Java绑定包装一个本地库来执行它自己的I / O呢? 那么本机代码应该如何挂钩到Thread并响应对Thread.interrupt()
调用呢?
有关完整写入(包括可运行的示例代码),请参阅https://github.com/NWilson/javaInterruptHook 。
Thread.interrupt()
如何工作? 在Sun的JRE(和OpenJDK)中, interrupt()
能够唤醒一些低级操作本身,例如在监视器上等待( Object.wait()
),并为更高级别的代码提供内部钩子。通知中断。 这是通过JavaLangAccess.blockedOn()
提供的,如果您愿意使用特定于Sun的实现细节,则可以通过sun.misc.SharedSecrets
直接通过代码直接调用它。
据我所知,只有一种公开的,记录的方式来注册该通知,即使用java.nio.channels.spi.AbstractSelector
。 这是Selector
的部分实现,它为您提供了将JavaLangAccess.blockedOn()
通知连接到选择器的wakeup()
方法的脏工作。
实现AbstractSelector
来创建自己的选择器; 大多数方法都不相关,所以只需忽略它们并放入存根来关闭编译器。 当您要输入JNI阻塞方法时,请调用AbstractSelector
begin()
方法,然后在返回JNI调用时调用end()
。
选择器应在其wakeup()
实现中取消JNI方法。
(有关完整运行的示例,请参阅顶部链接的github repo。)
class NativeTask {
public NativeTask() {}
public void doTask()
throws InterruptedException {
NativeTaskSelector selector = new NativeTaskSelector(this);
try {
selector.registerStart();
doTask0(); // native method
if (Thread.interrupted())
throw new InterruptedException();
} finally {
selector.registerEnd();
try { selector.close(); } catch (IOException impossible) {}
}
}
/* The long-running native operation. */
native private void doTask0();
public void wakeupTask() { wakeupTask0(); }
/* A way to cause the native operation to wake up. */
native private void wakeupTask0();
}
class NativeTaskSelector extends AbstractSelector {
protected NativeTaskSelector(NativeTask task_) {
super(null);
task = task_;
}
public void registerStart() { begin(); }
public void registerEnd() { end(); }
final private NativeTask task;
@Override
public Selector wakeup() {
task.wakeupTask();
return this;
}
@Override
protected void implCloseSelector() throws IOException {
}
@Override
protected SelectionKey register(AbstractSelectableChannel arg0, int arg1,
Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public Set<SelectionKey> keys() {
throw new UnsupportedOperationException();
}
@Override
public int select() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int select(long arg0) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int selectNow() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Set<SelectionKey> selectedKeys() {
throw new UnsupportedOperationException();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.