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