簡體   English   中英

如何編寫響應`Thread.interrupt()`的本機代碼?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM