【面試】一篇文章幫你徹底搞清楚“I/O多路複用”和“非同步I/O”的前世今生
曾經的VIP服務
在網路的初期,網民很少,伺服器完全無壓力,那時的技術也沒有現在先進,通常用一個執行緒來全程跟蹤處理一個請求。因為這樣最簡單。
其實程式碼實現大家都知道,就是伺服器上有個ServerSocket在某個埠監聽,接收到客戶端的連線後,會建立一個Socket,並把它交給一個執行緒進行後續處理。
執行緒主要從Socket讀取客戶端傳過來的資料,然後進行業務處理,並把結果再寫入Socket傳回客戶端。
由於網路的原因,Socket建立後並不一定能立刻從它上面讀取資料,可能需要等一段時間,此時執行緒也必須一直阻塞著。在向Socket寫入資料時,也可能會使執行緒阻塞。
這裡準備了一個示例,主要邏輯如下:
客戶端:建立20個Socket並連線到伺服器上,再建立20個執行緒,每個執行緒負責一個Socket。
伺服器端:接收到這20個連線,建立20個Socket,接著建立20個執行緒,每個執行緒負責一個Socket。
為了模擬伺服器端的Socket在建立後不能立馬讀取資料,讓客戶端的20個執行緒分別休眠5-10之間的一個隨機秒數。
客戶端的20個執行緒會在第5秒到第10秒這段時間內陸陸續續的向伺服器端傳送資料,伺服器端的20個執行緒也會陸陸續續接收到資料。
/**
* @author lixinjie
* @since 2019-05-07
*/
public class BioServer {
static AtomicInteger counter = new AtomicInteger(0);
static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress("localhost", 8080));
while (true) {
Socket s = ss.accept();
processWithNewThread(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
static void processWithNewThread(Socket s) {
Runnable run = () -> {
InetSocketAddress rsa = (InetSocketAddress)s.getRemoteSocketAddress();
System.out.println(time() + "->" + rsa.getHostName() + ":" + rsa.getPort() + "->" + Thread.currentThread().getId() + ":" + counter.incrementAndGet());
try {
String result = readBytes(s.getInputStream());
System.out.println(time() + "->" + result + "->" + Thread.currentThread().getId() + ":" + counter.getAndDecrement());
s.close();
} catch (Exception e) {
e.printStackTrace();
}
};
new Thread(run).start();
}
static String readBytes(InputStream is) throws Exception {
long start = 0;
int total = 0;
int count = 0;
byte[] bytes = new byte[1024];
//開始讀資料的時間
long begin = System.currentTimeMillis();
while ((count = is.read(bytes)) > -1) {
if (start < 1) {
//第一次讀到資料的時間
start = System.currentTimeMillis();
}
total += count;
}
//讀完資料的時間
long end = System.currentTimeMillis();
return "wait=" + (start - begin) + "ms,read=" + (end - start) + "ms,total=" + total + "bs";
}
static String time() {
return sdf.format(new Date());
}
}
/**
* @author lixinjie
* @since 2019-05-07
*/
public class Client {
public static void main(String[] args) {
try {
for (int i = 0; i < 20; i++) {
Socket s = new Socket();
s.connect(new InetSocketAddress("localhost", 8080));
processWithNewThread(s, i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
static void processWithNewThread(Socket s, int i) {
Runnable run = () -> {
try {
//睡眠隨機的5-10秒,模擬資料尚未就緒
Thread.sleep((new Random().nextInt(6) + 5) * 1000);
//寫1M資料,為了拉長伺服器端讀資料的過程
s.getOutputStream().write(prepareBytes());
//睡眠1秒,讓伺服器端把資料讀完
Thread.sleep(1000);
s.close();
} catch (Exception e) {
e.printStackTrace();
}
};
new Thread(run).start();
}
static byte[] prepareBytes() {
byte[] bytes = new byte[1024*1024*1];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = 1;
}
return bytes;
}
}
執行結果如下:
-
相關推薦
【面試】一篇文章幫你徹底搞清楚“I/O多路複用”和“非同步I/O”的前世今生
曾經的VIP服務在網路的初期,網民很少,伺服器完全無壓力,那時的技術也沒有現在先進,通常用一個執行緒來全程跟蹤處理一個請求。因為這樣最簡單。其實程式碼實現大家都知道,就是伺服器上有個ServerSocket在某個埠監聽,接收到客戶端的連線後,會建立一個Socket,並把它交給一個執行緒進行後續處理。執行緒主要
一篇文章幫你瞭解LoRaWAN特性【轉自微信公眾號 智聯網事】
LoRa,相信做小無線開發的朋友都不會陌生,Semtech公司獨有的擴頻調製技術,能夠實現低功耗遠距離的Sub-1G無線傳輸;而LoRaWAN,因為涉及到協議,因此不是那麼廣為人知;本文,主要針對LoRaWAN協議進行一個總結,包括以下內容: LoRaWAN從哪裡來 LoRa
【收藏】一篇快速幫企業轉型區塊鏈的錦囊
不同 標準 兼容 決定 開發環境 評估 去中心化 舉例 狀態 無論對於哪一項技術來說,衡量技術成熟的標誌都在於這項技術的最終落地。對於區塊鏈這個行業來說,大家最關心的莫過於,什麽樣的企業適合踏入區塊鏈這個領域?以及什麽樣的應用可以解決當下企業、用戶遇到的一些問題。在10月1
【經典】一篇文章初識大資料,及大資料相關框架Hadoop、spark、flink等
今天看到一篇講得比較清晰的框架對比,這幾個框架的選擇對於初學分散式運算的人來說確實有點迷茫,相信看完這篇文章之後應該能有所收穫。 簡介 大資料是收集、整理、處理大容量資料集,並從中獲得見解所需的非傳統戰略和技術的總稱。雖然處理資料所需的計算能力或儲存容量早已超過一
一篇文章幫你建立自己的大資料知識體系!
現在大資料非常火爆,相信你一定看過不少關於大資料的書、文章、資訊,但基本上獲取的都是零碎的知識點,不成系統,沒有形成自己的知識體系,“看過很多知識點但依然搞不懂大資料”,然並卵。那麼,今天這篇文章呢,就帶大家從整體思路上,剖析大資料的產品設計架構和技術策略,幫助大家建立自己的
一篇文章讓你徹底瞭解Java內部類
內容整理自《Thinking in Java》(第四版) 第10章 PDF下載地址 什麼是內部類? 將一個類的定義,放在另一個類的定義內部,那這個類,就是內部類 為什麼需要內部類? 一般來說,內部類繼承自某個類或實現某個介面,內部類的程式碼操作建立其的
JAVA多執行緒————一篇文章讓你徹底征服多執行緒開發(一)
多執行緒的基本概念 執行緒指程序中的一個執行場景,也就是執行流程,那麼程序和執行緒有什麼區別呢? 每個程序是一個應用程式,都有獨立的記憶體空間 同一個程序中的執行緒共享其程序中的記憶體和資源(共享的記憶體是堆記憶體和方法區記憶體,棧記憶體不共享,
一篇文章讓你徹底征服多執行緒開發
多執行緒的基本概念 執行緒指程序中的一個執行場景,也就是執行流程,那麼程序和執行緒有什麼區別呢? 每個程序是一個應用程式,都有獨立的記憶體空間 同一個程序中的執行緒共享其程序中的記憶體和資源(共享的記憶體是堆記憶體和方法區記憶體,棧記憶體不共享,
JAVA多執行緒————一篇文章讓你徹底征服多執行緒開發
多執行緒的基本概念執行緒指程序中的一個執行場景,也就是執行流程,那麼程序和執行緒有什麼區別呢?每個程序是一個應用程式,都有獨立的記憶體空間同一個程序中的執行緒共享其程序中的記憶體和資源(共享的記憶體是堆記憶體和方法區記憶體,棧記憶體不共享,每個執行緒有自己的。)什麼是程序?一
MySQL命令,一篇文章替你全部搞定
MySQL的基本操作可以包括兩個方面:MySQL常用語句如高頻率使用的增刪改查(CRUD)語句和MySQL高階功能,如儲存過程,觸發器,事務處理等。而這兩個方面又可以細分如下:MySQL常用語句表(或者資料庫)的CRUD表資料的CRUD,其中表資料查詢使用最多,也更復雜。查詢可以按照單表還是多表可以分為:單表
[C/C++基礎知識] 一篇就讓你徹底搞懂qsort快速排序的文章
一. C語言實現qsort快速排序 這段介紹參考百度百科,編譯器函式庫自帶的快速排序函式qsort。使用qsort()排序並用 bsearch()搜尋是一個比較常用的組合,使用方便快
一篇文章讓你徹底明白區塊鏈有哪些應用場景
Ripple: 區塊鏈跨境支付與外匯結算系統 Ripple為銀行類金融機構提供跨境支付服務,希望取代環球同業銀行金融電訊協會(SWIFT)的跨境轉賬平臺,打造全球統一的網路金融傳輸協議;利用Ripple的跨賬本協議(Interledger Protocol),所有參與者都能看到同一個賬本,銀
一篇文章讓你徹底理解java中抽象類和介面
目錄 1、我所理解的抽象類 2、我所理解的介面 3、抽象類和介面本質區別 相信大家都有這種感覺:抽象類與介面這兩者有太多相似的地方,又有太多不同的地方。往往這二者可以讓初學者摸不著頭腦,無論是在
一篇文章帶你快速弄清楚什麼是終端
Linux的使用者可能每天都會接觸到 Bash、Shell、控制檯、終端。它們之間有什麼不同嗎?本文為你快速解釋這些概念以及它們的區別。 什麼是終端 首先我們來弄清楚什麼是終端(terminal)。按照百度百科的解釋是:“經由通訊設施向計算機輸入程式和資料或
對JVM還一知半解?這篇文章讓你徹底搞定JVM
對於Java開發者來說,想把自身能力提升到更高層次,某些JVM相關知識應該是優先順序很高的。比如
【Linux】I/O多路複用
五種IO模型 阻塞IO(等待魚上鉤) 在核心將資料準備好之前,系統呼叫會一直等待,所有的套接字,預設是阻塞模式。 等待,拷貝資料到buf中,(等待的時間長) 非阻塞IO(定期檢視是否有魚上鉤) 如果核心還未將資料
I/O多路複用機制(一)
在實際的開發中,我們經常會遇到這樣的場景,我們需要接受多個埠的資料、多個終端的資料抑或是多個檔案描述符對應的資料。那麼,遇到這樣的問題,你在程式中該怎麼做呢?通常的做法,在程式中對資料互動
Java網路程式設計與NIO詳解2:JAVA NIO 一步步構建I/O多路複用的請求模型
微信公眾號【黃小斜】作者是螞蟻金服 JAVA 工程師,專注於 JAVA 後端技術棧:SpringBoot、SSM全家桶、MySQL、分散式、中介軟體、微服務,同時也懂點投資理財,堅持學習和寫作,相信終身學習的力量!關注公眾號後回覆”架構師“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料
一文搞懂I/O多路複用及其技術
## 前言 高效能是每個程式設計師的追求,無論寫一行程式碼還是做一個系統,都希望能夠達到高效能的效果。高效能架構設計主要集中在兩方面: - 儘量提升單伺服器的效能,將單伺服器的效能發揮到極致 - 如果單伺服器無法支撐效能,設計伺服器叢集方案 單伺服器高效能的關鍵之一就是伺服器採取的網
【一篇文章帶你讀完《C++遊戲程式設計入門 第4版》】
《C++遊戲程式設計入門 第4版》下載地址:https://download.csdn.net/download/qq_23996157/10764030 有道雲筆記分享:http://note.youdao.com/noteshare?id=4604366ece0ac2950db30ade53