jdk的Selector 3 select的過程

2021-08-14 16:15:48 字數 3593 閱讀 9012

當呼叫了selectorimpl的select()方法的時候,同時會將所帶的引數,也就是給select()所設定的timeout,之後會呼叫lockanddoselect(),在這個方法中,主要還是呼叫了doselect()方法,引數與傳進來的一致。以windowsselectorimpl為例子,實現的deselect()方法。

protected int doselect(long var1) throws ioexception  else  else  catch (ioexception var7) 

if(this.threads.size() > 0)

} finally

this.finishlock.checkforexception();

this.processderegisterqueue();

int var3 = this.updateselectedkeys();

this.resetwakeupsocket();

return var3;}}

}

首先,會呼叫processderegisterqueue()方法,來將已經準備解除註冊的channel進行解除註冊。

void processderegisterqueue() throws ioexception  catch (socketexception var12)  finally }}

}}

在這裡,會取得所有需要取消註冊的selectionkey,並且依次呼叫impldereg()進行解除繫結。

protected void impldereg(selectionkeyimpl var1) throws ioexception 

var1.setindex(-1);

}this.channelarray[this.totalchannels - 1] = null;

--this.totalchannels;

if(this.totalchannels != 1 && this.totalchannels % 1024 == 1)

this.fdmap.remove(var1);

this.keys.remove(var1);

this.selectedkeys.remove(var1);

this.deregister(var1);

selectablechannel var7 = var1.channel();

if(!var7.isopen() && !var7.isregistered())

}

如果需要解除註冊的channel已經是selector當中最後乙個了,那麼直接從陣列中移走就行,但如果沒有,則需要與陣列最後乙個索引位置上的交換位置,保證陣列中間位置的連續,再將其移除,後面的操作與註冊的操作相似,但都是反向操作。

在完成取消註冊的步驟後,將會呼叫adjustthreadcount()方法來調整執行緒的數量,具體看下面的方法。

private void adjustthreadscount() 

} else if(this.threadscount < this.threads.size())

}}

在selector中,每有1024條channel,就需要重新開乙個執行緒加入完成監聽的操作,這裡是從新根據當前應該有的執行緒數量與此時現存的執行緒數量進行比較,動態調整。

在這之後,呼叫了begin()方法,準備開始正式進行select操作。

protected final void begin() };

}abstractinterruptiblechannel.blockedon(interruptor);

thread me = thread.currentthread();

if (me.isinterrupted())

interruptor.interrupt(me);

}

在這裡的begin()方法判斷了這裡的interruptor是否為空,如果為空,則會在這裡重新生成乙個,這裡的interruptor保證了當執行緒阻塞在了io操作上,並且被interruptor時,保證selecor能夠被喚醒。

在begin()方法執行完畢之後,將會呼叫其subselector的poll()方法,正式開始select操作。

private int poll() throws ioexception 

private int poll(int var1) throws ioexception

private native int poll0(long var1, int var3, int var4, int var5, int var6, long var7);

當完成資料監聽,取得相應的資料的時候,在這之後,將會重新檢驗並取消一邊已經被取消的channel之後呼叫updateselectedkeys()方法。

private int processselectedkeys(long var1) 

private int processfdset(long var1, int var3, int var4, boolean var5)

} else

} else if(var10.channel.translateandupdatereadyops(var4, var10) && var9.updatecount != var1)

var9.clearedcount = var1;

} else

} else

}var9.clearedcount = var1;}}

}}

}return var6;

}

private int updateselectedkeys() 

return var4;

}

這裡,將會在所有執行緒中呼叫processselectedkeys()來對所有執行緒在poll過程中取得的結果進行處理,並返回所有執行緒中處理的channel的數量。

private int processselectedkeys(long var1) 

private int processfdset(long var1, int var3, int var4, boolean var5)

} else

} else if(var10.channel.translateandupdatereadyops(var4, var10) && var9.updatecount != var1)

var9.clearedcount = var1;

} else

} else

}var9.clearedcount = var1;}}

}}

}return var6;

}

這裡實則是對在之前的監聽到發生了io時間需要處理的fd與對應的channel進行操作,根據讀到的fd取得selector下註冊了的相應的channel,根據監聽到其所發生的時間型別(讀,寫,異常)更新channel應有的狀態,這是其主要功能,在完成這些操作之後,相應的slector的select也相應完成。

HTML5新增的3種selector方法

1 queryselector 方法接收乙個css選擇符,返回與該模式匹配的第乙個元素,如果沒有找到匹配的元素,返回null。lang en charset utf 8 titletitle head style height 100 class box id box style height 20...

git clone 踩過的坑3

報錯 please wait a moment.remote counting objects 864,done remote finding sources 100 348 348 packet write wait connection to xx.xx.xx.xx port broken pi...

使用Select的3個注意事項

include int select int n,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout int pselect int n,fd set readfds,fd set writefds,fd se...