<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Netty之線程喚醒wakeup [續(xù)]

          共 2564字,需瀏覽 6分鐘

           ·

          2021-09-18 00:12

          在之前的Netty之線程喚醒wakeup文章中, 介紹了如何喚醒Netty中的監(jiān)聽線程. 接下來我們通過部分源碼,結(jié)合一些命令和實(shí)驗(yàn),看一下它的實(shí)現(xiàn).


          // WakeUp.javaimport java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.net.ServerSocket;
          public class WakeUp {
          public static void main(String[] args) throws Exception { // 底層創(chuàng)建管道Pipe和Epoll final Selector selector = Selector.open(); // 創(chuàng)建用于監(jiān)聽的socket ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); ServerSocket socket = serverSocketChannel.socket();
          socket.bind(new InetSocketAddress("127.0.0.1", 8080), 64); serverSocketChannel.configureBlocking(false); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
          new Thread() { @Override public void run() { try { System.out.print("Thread[" + Thread.currentThread().getName() + "]invoke select\r\n"); // 線程阻塞在這里 int readyChannels = selector.select(); } catch (Exception x) { x.printStackTrace(); } System.out.print("Success...\r\n"); } }.start(); }}


          我們先看第一句話


          Selector selector = Selector.open();

          這句話是要創(chuàng)建一個Selector,在Linux系統(tǒng)下,是在EpollSelectorImpl.java文件中.





          我們可以理解成

          Selector selector = new EPollSelectorImpl(sp);



          通過makePipe(false)方法創(chuàng)建了一個管道,管道的一端通過int fd0表示, 管道另一端通過int fd1表示 .


          接下來就是創(chuàng)建epoll相關(guān)的信息.

          接下來就是把管道的一端添加到epoll的紅黑樹上,交由epoll監(jiān)管.


          把fd0添加到epoll中管理,這樣當(dāng)我們向fd1寫數(shù)據(jù)的時候,epoll發(fā)現(xiàn)fd0有數(shù)據(jù)可以讀取了(數(shù)據(jù)是從fd1流向fd0),于是就把與epoll對應(yīng)的那個線程給喚醒了(后面有圖片,可以形象一些).

          當(dāng)我們執(zhí)行上面的Java程序時,通過查看進(jìn)程的文件描述符,就可以很明顯的看到這個管道


          8號文件描述符用于監(jiān)聽客戶端的連接.



          5和8號文件描述符添加到epoll中,交由epoll管理它們.

          總結(jié)一下,創(chuàng)建一個epoll套接字用于管理其他文件描述符. 創(chuàng)建一個管道,其中管道的一端(5號套接字)交給epoll管理, 8號服務(wù)端套接字也交給epoll管理.效果如下圖




          7號epoll套接字管理著5號和8號, 即便此時客戶端還沒有連接到8號監(jiān)聽套接字,此時IO線程阻塞住了,我們依然可以通過6號管道一端寫數(shù)據(jù),然后epoll監(jiān)聽到5號管道有數(shù)據(jù)到來,于是乎就可以把IO線程給喚醒 . 至于向6號管道寫什么數(shù)據(jù),不是那么重要,比如下面的視頻,我們向6號管道寫了一個1,甚至我們什么多不寫都可以,依然可以喚醒阻塞的IO線程.



          做了一個簡短演示視頻

           


          視頻中,通過echo命令給管道的一端寫入數(shù)據(jù),那么epoll'發(fā)現(xiàn)'管道的另一端有數(shù)據(jù)到來,于是從阻塞狀態(tài)'醒來'.


          以上是在Linux平臺下,喚醒select線程是通過管道的方式,而在Windows平臺,卻不是通過管道的方式 .


          我們把上面的Java代碼在Windows平臺編譯并運(yùn)行它

          通過TCPView工具查看



          我們發(fā)現(xiàn),在進(jìn)程內(nèi)有一對TCP連接,那么這對TCP連接就是類似上面說的管道的作用,用來喚醒阻塞在select方法的線程. 我們可以通過關(guān)閉某個TCP連接,看一下阻塞在select方法的線程是否會被喚醒.







          做了一個簡短演示視頻



          視頻中,通過關(guān)閉某個TCP連接,向?qū)Χ说腡CP發(fā)送數(shù)據(jù),那么epoll'發(fā)現(xiàn)'TCP的另一端被關(guān)閉,于是從阻塞狀態(tài)'醒來'.




          本篇主要講解在Linux平臺和Windows平臺, 被阻塞在select方法的IO線程是通過什么手段被喚醒的.在Linux平臺是通過管道的方式, 而在Windows平臺是通過TCP連接的方式.

          瀏覽 30
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产黄色毛片网站 | 免费A V在线播放 | 人人干人人插 | 青青影视99 | 天天天天天天天天干 |