Java 作用域中断是否存在?

Java 作用域中断是否存在?,java,networking,concurrency,locking,css-selectors,Java,Networking,Concurrency,Locking,Css Selectors,某些系统要求我提供作用域中断,这样当thread.sleep(..)不执行时,中断线程是禁用的。我通常会使用保护块,这将很好地工作,但在这种情况下,有几个原因我不能,主要是因为争用阻止了整个事情正常工作。模拟在几秒钟内就停止了。作用域中断将取代任何阻塞机制,并防止中断在测试中断的方法之外“泄漏”。在本例中,它应该是Thread.sleep(…)。然而,我想知道这是否要求一些在Java中根本不可能的东西。也许防护阻塞机制是最好的 我已经创建了自己的选择器实现,用于网络模拟器(选择器与模拟器回调交互

某些系统要求我提供作用域中断,这样当thread.sleep(..)不执行时,中断线程是禁用的。我通常会使用保护块,这将很好地工作,但在这种情况下,有几个原因我不能,主要是因为争用阻止了整个事情正常工作。模拟在几秒钟内就停止了。作用域中断将取代任何阻塞机制,并防止中断在测试中断的方法之外“泄漏”。在本例中,它应该是
Thread.sleep(…)
。然而,我想知道这是否要求一些在Java中根本不可能的东西。也许防护阻塞机制是最好的

我已经创建了自己的选择器实现,用于网络模拟器(选择器与模拟器回调交互,并进行优化),目前基本上我使用的是
CountDownLatch
。这在某些情况下是好的,而在另一些情况下,它会创建更糟糕的阻塞,同时不会冻结整个模拟本身(但是,它太慢以至于无法工作)。这取决于所使用的网络框架,即代码的哪些部分比其他部分受到的影响更大。我还认为,在“良好”的模拟中,问题可能会出现,很少出现,导致等待13毫秒,因此,当获得内部倒计时锁存器或内部发生任何魔法时

如果您不需要上述任何建议就可以解决此问题,那将是令人惊讶的:)无论如何,我的代码如下:

/**
 *
 */
package kokunet;

import java.io.IOException;
import java.nio.channels.ClosedSelectorException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import kokuks.IConnectionSocket;
import kokuks.KKSAddress;
import kokuks.KKSSocket;
import kokuks.KKSSocketListener;

public class KSelector extends SelectorImpl {
    // True if this Selector has been closed
    private volatile boolean closed = false;

    // Lock for close and cleanup
    final class CloseLock {}
    private final Object closeLock = new CloseLock();

    private volatile boolean selecting = false;
    private volatile boolean wakeup = false;

    class SocketListener implements KKSSocketListener {
        protected volatile CountDownLatch latch = null;

        /**
         *
         */
        public SocketListener() {
            newLatch();
        }

        protected synchronized CountDownLatch newLatch() {
            return this.latch = new CountDownLatch(1);
        }

        protected synchronized void refreshReady(KKSSocket socket) {
            if (!selecting) return;

            synchronized (socketToChannel) {
                SelChImpl ch = socketToChannel.get(socket);
                if (ch == null) {
                    System.out.println("ks sendCB: channel not found for socket: " + socket);
                    return;
                }
                synchronized (channelToKey) {
                    SelectionKeyImpl sk = channelToKey.get(ch);
                    if (sk != null) {
                        if (handleSelect(sk)) {
                            latch.countDown();
                        }
                    }
                }
            }
        }
        @Override
        public void connectionSucceeded(KKSSocket socket) {
            refreshReady(socket);
        }
        @Override
        public void connectionFailed(KKSSocket socket) {
            refreshReady(socket);
        }
        @Override
        public void dataSent(KKSSocket socket, long bytesSent) {
            refreshReady(socket);
        }
        @Override
        public void sendCB(KKSSocket socket, long bytesAvailable) {
            refreshReady(socket);
        }
        @Override
        public void onRecv(KKSSocket socket) {
            refreshReady(socket);
        }
        @Override
        public void newConnectionCreated(KKSSocket socket, KKSSocket newSocket, KKSAddress remoteaddress) {
            refreshReady(socket);
        }
        @Override
        public void normalClose(KKSSocket socket) {
            wakeup();
        }
        @Override
        public void errorClose(KKSSocket socket) {
            wakeup();
        }
    }

    protected final Map<KKSSocket, SelChImpl>        socketToChannel = new HashMap<KKSSocket, SelChImpl>();
    protected final Map<SelChImpl, SelectionKeyImpl> channelToKey    = new HashMap<SelChImpl, SelectionKeyImpl>();
    protected final SocketListener currListener = new SocketListener();

    SelChImpl getChannelForSocket(KKSSocket s) {
        synchronized (socketToChannel) {
            return socketToChannel.get(s);
        }
    }

    SelectionKeyImpl getSelKeyForChannel(KKSSocket s) {
        synchronized (channelToKey) {
            return channelToKey.get(s);
        }
    }

    protected boolean markRead(SelectionKeyImpl impl) {
        synchronized (impl) {
            if (!impl.isValid()) return false;
            impl.nioReadyOps(impl.readyOps() | SelectionKeyImpl.OP_READ);
            return selectedKeys.add(impl);
        }
    }

    protected boolean markWrite(SelectionKeyImpl impl) {
        synchronized (impl) {
            if (!impl.isValid()) return false;
            impl.nioReadyOps(impl.readyOps() | SelectionKeyImpl.OP_WRITE);
            return selectedKeys.add(impl);
        }
    }

    protected boolean markAccept(SelectionKeyImpl impl) {
        synchronized (impl) {
            if (!impl.isValid()) return false;
            impl.nioReadyOps(impl.readyOps() | SelectionKeyImpl.OP_ACCEPT);
            return selectedKeys.add(impl);
        }
    }

    protected boolean markConnect(SelectionKeyImpl impl) {
        synchronized (impl) {
            if (!impl.isValid()) return false;
            impl.nioReadyOps(impl.readyOps() | SelectionKeyImpl.OP_CONNECT);
            return selectedKeys.add(impl);
        }
    }

    /**
     * @param provider
     */
    protected KSelector(SelectorProvider provider) {
        super(provider);
    }

    /* (non-Javadoc)
     * @see kokunet.SelectorImpl#implClose()
     */
    @Override
    protected void implClose() throws IOException {
        provider().getApp().printMessage("implClose: closed: " + closed);
        synchronized (closeLock) {
            if (closed) return;
            closed = true;
            for (SelectionKey sk : keys) {
                provider().getApp().printMessage("dereg1");
                deregister((AbstractSelectionKey)sk);
                provider().getApp().printMessage("dereg2");
                SelectableChannel selch = sk.channel();
                if (!selch.isOpen() && !selch.isRegistered())
                    ((SelChImpl)selch).kill();
            }
            implCloseInterrupt();
        }
    }

    protected void implCloseInterrupt() {
        wakeup();
    }

    private boolean handleSelect(SelectionKey k) {
        synchronized (k) {
            boolean notify = false;

            if (!k.isValid()) {
                k.cancel();
                ((SelectionKeyImpl)k).channel.socket().removeListener(currListener);
                return false;
            }

            SelectionKeyImpl ski = (SelectionKeyImpl)k;

            if ((ski.interestOps() & SelectionKeyImpl.OP_READ) != 0) {
                if (ski.channel.socket().getRxAvailable() > 0) {
                    notify |= markRead(ski);
                }
            }

            if ((ski.interestOps() & SelectionKeyImpl.OP_WRITE) != 0) {
                if (ski.channel.socket().getTxAvailable() > 0) {
                    notify |= markWrite(ski);
                }
            }

            if ((ski.interestOps() & SelectionKeyImpl.OP_CONNECT) != 0) {
                if (!ski.channel.socket().isConnectionless()) {
                    IConnectionSocket cs = (IConnectionSocket)ski.channel.socket();
                    if (!ski.channel.socket().isAccepting() && !cs.isConnecting() && !cs.isConnected()) {
                        notify |= markConnect(ski);
                    }
                }
            }

            if ((ski.interestOps() & SelectionKeyImpl.OP_ACCEPT) != 0) {
                //provider().getApp().printMessage("accept check: ski: " + ski + ", connectionless: " + ski.channel.socket().isConnectionless() + ", listening: " + ski.channel.socket().isListening() + ", hasPendingConn: " + (ski.channel.socket().isConnectionless() ? "nope!" : ((IConnectionSocket)ski.channel.socket()).hasPendingConnections()));
                if (!ski.channel.socket().isConnectionless() && ski.channel.socket().isListening()) {
                    IConnectionSocket cs = (IConnectionSocket)ski.channel.socket();
                    if (cs.hasPendingConnections()) {
                        notify |= markAccept(ski);
                    }
                }
            }
            return notify;
        }
    }

    private boolean handleSelect() {
        boolean notify = false;

        // get initial status
        for (SelectionKey k : keys) {
            notify |= handleSelect(k);
        }

        return notify;
    }

    /* (non-Javadoc)
     * @see kokunet.SelectorImpl#doSelect(long)
     */
    @Override
    protected int doSelect(long timeout) throws IOException {
        processDeregisterQueue();

        long timestartedms = System.currentTimeMillis();

        synchronized (selectedKeys) {
            wakeup = false;
            selecting = true;
            try {
                handleSelect();

                if (!selectedKeys.isEmpty() || timeout == 0) {
                    return selectedKeys.size();
                }

                //TODO: useless op if we have keys available
                for (SelectionKey key : keys) {
                    ((SelectionKeyImpl)key).channel.socket().addListener(currListener);
                }
                try {
                    while (!wakeup && isOpen() && selectedKeys.isEmpty()) {
                        CountDownLatch latch = null;
                        synchronized (currListener) {
                            if (wakeup || !isOpen() || !selectedKeys.isEmpty()) {
                                break;
                            }
                            latch = currListener.newLatch();
                        }
                        try {
                            if (timeout > 0) {
                                long currtimems = System.currentTimeMillis();
                                long remainingMS = (timestartedms + timeout) - currtimems;

                                if (remainingMS > 0) {
                                    latch.await(remainingMS, TimeUnit.MILLISECONDS);
                                } else {
                                    break;
                                }
                            } else {
                                latch.await();
                            }
                        } catch (InterruptedException e) {
                            wakeup();
                        }
                    }
                    return selectedKeys.size();
                } finally {
                    for (SelectionKey key : keys) {
                        ((SelectionKeyImpl)key).channel.socket().removeListener(currListener);
                    }
                    processDeregisterQueue();
                }
            } finally {
                selecting = false;
                wakeup = false;
            }
        }
    }

    /* (non-Javadoc)
     * @see kokunet.SelectorImpl#implRegister(kokunet.SelectionKeyImpl)
     */
    @Override
    protected void implRegister(SelectionKeyImpl ski) {
        synchronized (closeLock) {
            if (closed) throw new ClosedSelectorException();
            synchronized (channelToKey) {
                synchronized (socketToChannel) {
                    keys.add(ski);
                    socketToChannel.put(ski.channel.socket(), ski.channel);
                    channelToKey.put(ski.channel, ski);
                }
            }
        }

    }

    /* (non-Javadoc)
     * @see kokunet.SelectorImpl#implDereg(kokunet.SelectionKeyImpl)
     */
    @Override
    protected void implDereg(SelectionKeyImpl ski) throws IOException {
        synchronized (channelToKey) {
            synchronized (socketToChannel) {
                keys.remove(ski);
                socketToChannel.remove(ski.channel.socket());
                channelToKey.remove(ski.channel);

                SelectableChannel selch = ski.channel();

                if (!selch.isOpen() && !selch.isRegistered())
                    ((SelChImpl)selch).kill();
            }
        }
    }

    /* (non-Javadoc)
     * @see kokunet.SelectorImpl#wakeup()
     */
    @Override
    public Selector wakeup() {
        synchronized (selectedKeys) {
            wakeup = true;
            selectedKeys.notifyAll();
        }
        return this;
    }
}
/**
*
*/
包kokunet;
导入java.io.IOException;
导入java.nio.channels.ClosedSelectorException;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.concurrent.CountDownLatch;
导入java.util.concurrent.TimeUnit;
导入kokuks.i连接插座;
进口kokuks.kksadress;
进口kokuks.KKSSocket;
导入kokuks.KKSSocketListener;
公共类KSelector扩展SelectorImpl{
//如果此选择器已关闭,则为True
私有易失性布尔闭合=假;
//锁定以关闭和清理
最终类CloseLock{}
私有最终对象closeLock=新closeLock();
私有易失性布尔选择=false;
私有易失性布尔唤醒=false;
类SocketListener实现KKSSocketListener{
受保护的易失性倒计时闩锁=空;
/**
*
*/
公共SocketListener(){
newLatch();
}
受保护的同步倒计时闩锁newLatch(){
返回this.latch=新的倒计时闩锁(1);
}
受保护的同步空刷新就绪(KKSSocket套接字){
如果(!选择)返回;
同步(socketToChannel){
SelChImpl ch=socketToChannel.get(套接字);
if(ch==null){
System.out.println(“ks sendCB:未找到套接字的通道:“+socket”);
返回;
}
已同步(Channely){
SelectionKeyImpl sk=channelToKey.get(ch);
if(sk!=null){
if(手动选择(sk)){
倒计时();
}
}
}
}
}
@凌驾
公共无效连接已成功(KKSSocket插座){
刷新准备(插座);
}
@凌驾
公共无效连接失败(KKSSocket套接字){
刷新准备(插座);
}
@凌驾
public void dataSent(KKSSocket套接字,long bytesent){
刷新准备(插座);
}
@凌驾
public void sendCB(KKSSocket套接字,长字节可用){
刷新准备(插座);
}
@凌驾
公共无效onRecv(KKSSocket插座){
刷新准备(插座);
}
@凌驾
public void newConnectionCreated(KKSSocket套接字、KKSSocket newSocket、KKSAddress远程地址){
刷新准备(插座);
}
@凌驾
公共无效正常关闭(KKSSocket插座){
唤醒();
}
@凌驾
公共无效错误关闭(KKSSocket插座){
唤醒();
}
}
受保护的最终映射socketToChannel=new HashMap();
受保护的最终映射channelToKey=new HashMap();
受保护的最终SocketListener currListener=新SocketListener();
SelChImpl getChannelForSocket(KKSSocket s){
同步(socketToChannel){
返回socketToChannel.get(s);
}
}
选择KeyImpl getSelKeyForChannel(KKSSocket s){
已同步(Channely){
返回channelToKey.get(s);
}
}
受保护的布尔标记读取(SelectionKeyImpl){
已同步(impl){
如果(!impl.isValid())返回false;
impl.nioReadyOps(impl.readyOps()| SelectionKeyImpl.OP_READ);
返回所选键。添加(impl);
}
}
受保护的布尔标记写入(SelectionKeyImpl){
已同步(impl){
如果(!impl.isValid())返回false;
impl.nioReadyOps(impl.readyOps()| SelectionKeyImpl.OP|u WRITE);
返回所选键。添加(impl);
}
}
受保护的布尔标记接受(SelectionKeyImpl){
已同步(impl){
如果(!impl.isValid())返回false;
impl.nioReadyOps(impl.readyOps()| SelectionKeyImpl.OP|u ACCEPT);
返回所选键。添加(impl);
}
}
受保护的布尔标记连接(SelectionKeyImpl){
已同步(impl){
如果(!impl.isValid())返回false;
impl.nioReadyOps(impl.readyOps()| SelectionKeyImpl.OP_CONNECT);
返回所选键。添加(impl);
}
}
/**
*@param提供程序
*/
受保护的K选择程序(选择程序或提供程序)