当前位置:网站首页>NIO this.selector.select()
NIO this.selector.select()
2022-07-27 08:42:00 【Mangxiao】
NIO this.selector.select
Process carding :
1. SelectorImpl.lockAndDoSelect()
2. windowsSelectorImpl.doSelect Officially start polling events
2.1 subSelector.poll(); Start the bottom polling , Get ready file descriptor
2.2 this.updateSelectedKeys(); Will be ready key Add to selectedKeys in , Enter the method
2.2.1 this.subSelector.processSelectedKeys(this.updateCount); Call... On the main thread poll after , Will get the ready file descriptor ( Include readable 、 Can write 、 abnormal ). By calling processSelectedKeys Corresponding to the ready file descriptor SelectorKey Add to selectedKeys in . In this way, we can call all ready SelectorKey Do traversal processing .



SelectorImpl.lockAndDoSelect()

a key : Finally, execute SelectorImpl.doSelect, stay windows Platform by WindowsSelectorImpl Realization
WindowsSelectorImpl#doSelect


Analyze one by one
protected int doSelect(long var1) throws IOException {
// First of all to see Selector If there Channel, If not, throw an exception
if (this.channelArray == null) {
throw new ClosedSelectorException();
} else {
this.timeout = var1;
this.processDeregisterQueue();
Set interrupter , What's actually called is AbstractSelector.this.wakeup(); Method
// The method is called AbstractInterruptibleChannel.blockedOn(Interruptible);
if (this.interruptTriggered) {
this.resetWakeupSocket();
return 0;
} else {
// Adjust the number of worker threads
this.adjustThreadsCount();
// Adjust the running relationship between the main thread and the auxiliary thread
this.finishLock.reset();
this.startLock.startThreads();
try {
this.begin();
try {
// perform poll Method
this.subSelector.poll();
} catch (IOException var7) {
this.finishLock.setException(var7);
}
if (this.threads.size() > 0) {
this.finishLock.waitForHelperThreads();
}
} finally {
this.end();
}
this.finishLock.checkForException();
this.processDeregisterQueue();
int var3 = this.updateSelectedKeys();
this.resetWakeupSocket();
return var3;
}
}
}
adjustThreadsCount
As you can see from the notes , The method in NIO in channel After registration or logout , Adjust the number of worker threads . among threads.size() Is the current number of worker threads ,threadsCount For the number of worker threads needed . If the current quantity is less than the required quantity , Create a new worker thread , To achieve the required quantity . If the current quantity is greater than the required quantity , Then kill the redundant threads .

Auxiliary thread : A thread can only handle 1024 individual Channel, If there are too many, you need to provide auxiliary threads other than the main thread , In the Selector register Channel Auxiliary threads will be added according to conditions , To selector.select Will judge when .
processDeregisterQueue
Process logged out SelectionKey
updateSelectedKeys —— a key : Discovery of the arrival of the event

SubSelector
poll —— Interact with the kernel to find events of interest

processSelectedKeys —— Handle events of interest found from the kernel
updateSelectedKeys Be responsible for handling readiness events FD, Will these FD The corresponding selection key is added selectedKeys aggregate . The client traverses selectedKeys Collection can handle various events . Look at the source code
updateSelectedKeys The first call processSelectedKeys Handle the ready event on the main thread FD list . Then iteration threads The collection processes the ready events on each worker thread separately FD list . see processSelectedKeys Realization :
processSelectedKeys It's easy to implement , Deal with... Separately readFds,writeFds,exceptFds In three arrays FD, The core processing process is in processFDSet To realize 
processFDSet
To deal with readFds For example
Parameter interpretation :
var1: this.updateCount, Save the number of updates
var3: this.readFds, Readable file descriptor array , What is stored here is Channel File descriptor for , The first element of the file descriptor is the length of the array , Then comes the value of the file descriptor


private int processFDSet(long var1, int[] var3, int var4, boolean var5) {
// Store the number of prepared events
int var6 = 0;
//1. Take the readable file event as an example ,var3 Is an array of file descriptors var3[0] It represents the length of the file descriptor stored in the array
for(int var7 = 1; var7 <= var3[0]; ++var7) {
// Get the value of the file descriptor fdVal
int var8 = var3[var7];
//2. Determine whether the current file descriptor is a file description for wakeup
if (var8 == WindowsSelectorImpl.this.wakeupSourceFd) {
synchronized(WindowsSelectorImpl.this.interruptLock) {
WindowsSelectorImpl.this.interruptTriggered = true;
}
} else {
// according to fdval Get selector Medium FdMap Medium SelectionKeyImpl
WindowsSelectorImpl.MapEntry var9 = WindowsSelectorImpl.this.fdMap.get(var8);
if (var9 != null) {
// Get SelectionKeyImpl
SelectionKeyImpl var10 = var9.ski;
if (!var5 || !(var10.channel() instanceof SocketChannelImpl) || !WindowsSelectorImpl.this.discardUrgentData(var8)) {
if (WindowsSelectorImpl.this.selectedKeys.contains(var10)) {
if (var9.clearedCount != var1) {
if (var10.channel.translateAndSetReadyOps(var4, var10) && var9.updateCount != var1) {
var9.updateCount = var1;
++var6;
}
} else if (var10.channel.translateAndUpdateReadyOps(var4, var10) && var9.updateCount != var1) {
var9.updateCount = var1;
++var6;
}
var9.clearedCount = var1;
} else {
if (var9.clearedCount != var1) {
// updated SelectionKeyImpl Ready Events
var10.channel.translateAndSetReadyOps(var4, var10);
// In fact, it is to check whether the event you are interested in is a ready event , That is, the event you are interested in has passed the verification and can be processed later .
if ((var10.nioReadyOps() & var10.nioInterestOps()) != 0) {
// Will be selectionKeys Add to Selector Of set In the data structure
WindowsSelectorImpl.this.selectedKeys.add(var10);
//
var9.updateCount = var1;
++var6;
}
} else {
var10.channel.translateAndUpdateReadyOps(var4, var10);
if ((var10.nioReadyOps() & var10.nioInterestOps()) != 0) {
WindowsSelectorImpl.this.selectedKeys.add(var10);
var9.updateCount = var1;
++var6;
}
}
var9.clearedCount = var1;
}
}
}
}
}
// here var6>0, Express Channel The interested events can be processed after verification ,
return var6;
}
}

translateAndSetReadyOps



First, look into the reference var3, In fact, it is the first one we created Channel,ServerSocketChannel Corresponding SelectionKeyImpl, It is interested in reading events ( Because of its interestOps by 16, You can see in the following code )
Why 16, Because the event it is interested in is OP_ACCEPT
public boolean translateReadyOps(int var1, int var2, SelectionKeyImpl var3) {
// Take it SelectionKeyImpl Events of interest and prepared event types in
int var4 = var3.nioInterestOps(); #16
int var5 = var3.nioReadyOps(); #0
int var6 = var2;
//Net.POLLNVAL Indicates that the socket file is not open , As mentioned above var1 representative NET.POLLIN Indicates that there are readable events , Generally, this constant is defined as 00001,00010 Bits in this form , The operation of and is actually to compare whether the two are equal . It's obviously not equal here
if ((var1 & Net.POLLNVAL) != 0) {
return false;
// The meaning of this step is actually whether the event is Net.POLLERR、Net.POLLHUP One of them, one of them 00001, One is 00010, The two carry out or operation 00011, as long as var1 It's one of them , And operation is not 0 .NET.POLLIN 768 amount to 1100000000 That is to say 512+256
} else if ((var1 & (Net.POLLERR | Net.POLLHUP)) != 0) {
var3.nioReadyOps(var4);
return (var4 & ~var5) != 0;
} else {
// The meaning expressed here : This is a judgment of reading events and SelectionKeyImpl Is interested in the event of reading , Because we can see from above SelectionKeyImpl Of interestOps by 16, therefore var4 & 16) != 0 Is established
if ((var1 & Net.POLLIN) != 0 && (var4 & 16) != 0) {
//var6 =16
var6 = var2 | 16;
}
// Key step : Express SelectionKeyImpl The read event for is ready : To inform Channel: Here comes the reading event you are interested in !
var3.nioReadyOps(var6);
return (var6 & ~var5) != 0; // This step is worth detailing ,SelectionKeyImpl By bit InterestOps and ReadyOps The storage , A bit sequence can store multiple events of interest , It is the operation between bits that may make people confused , Can't , It's better to save money than brains . Here you only need to know the return true.
}
}
边栏推荐
猜你喜欢

Digital intelligence innovation

海关总署:这类产品暂停进口

网络IO总结文

Include error in vs Code (new header file)

“鼓浪屿元宇宙”,能否成为中国文旅产业的“升级样本”

How to view instances of software objects in QSIM?

Interviewer: what is scaffolding? Why do you need scaffolding? What are the commonly used scaffolds?

Login to homepage function implementation

Process control - Branch

How to merge multiple columns in an excel table into one column
随机推荐
Chapter 2 foreground data display
2034: [Blue Bridge Cup 2022 preliminary] pruning shrubs
P7 Day1 get to know the flask framework
User management - restrictions
Flask one to many database creation, basic addition, deletion, modification and query
Bandwidth and currency
arguments
E. Split into two sets
Matlab 利用M文件产生模糊控制器
Vertical align cannot align the picture and text vertically
Include error in vs Code (new header file)
UVM入门实验1
The following license SolidWorks Standard cannot be obtained, and the use license file cannot be found. (-1,359,2)。
Day3 -- flag state holding, exception handling and request hook
Forced login, seven cattle cloud upload pictures
Create a project to realize login and registration, generate JWT, and send verification code
regular expression
Blueprint class view method
How to permanently set source
MySQL Express




