<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
非同步:傳送請求無需等待響應,程式接著往下走。
事件驅動:一個連線事件或者斷開事件,或者讀事件或者寫事件,發生後的後續處理。
Netty典型應用:
簡單理解就是用什麼通道去進行資料傳送和接收。
BIO:一個連線一個執行緒,連線不做任何事會造成不必要的執行緒開銷。適用於連線數目較小且固定的架構。
NIO:伺服器端一個執行緒(也可以多個),維護一個多路複用器。由多路複用器去處理IO執行緒。適用於連線數目多且較短的架構
AIO:非同步非阻塞,還未得到廣泛應用。適用於連線數目多且連線較長的架構。
public class BIOserver { public static void main(String[] args) throws IOException { // 為了方便直接用了Executors建立執行緒池 ExecutorService service = Executors.newCachedThreadPool(); //指定伺服器端埠 ServerSocket serverSocket = new ServerSocket(6666); System.out.println("伺服器啟動"); while(true){ //阻塞等待連線 Socket socket = serverSocket.accept(); System.out.println("連線到一個使用者端"); //每個連線對應一個執行緒 service.execute(new Runnable() { @Override public void run() { try { handler(socket); }catch (Exception e){ e.printStackTrace(); } } }); } } public static void handler(Socket socket) throws IOException { System.out.println("Thread:"+Thread.currentThread().getId()); byte[] bytes = new byte[1024]; InputStream inputStream = socket.getInputStream(); while (true){ //阻塞等待讀取 int n = inputStream.read(bytes); if(n!=-1){ System.out.println(new String(bytes,0,n)); }else { break; } } socket.close(); } }
測試:使用windows的telnet
使用 ctrl+]
可以在伺服器端控制檯看到,已經讀取到傳送的資料
三大核心部分:Channel(可類比Socket),Buffer,Selector
大概是這個樣子。使用者端和Buffer互動,Buffer和Channel是一對一的關係。Selector選擇操作Channel(事件驅動,如果Channel有事件發生,Selector才去選擇操作。)
ByteBuffer使用場景較為廣泛。
buffer就是一個記憶體塊,所以說nio是面向塊/緩衝,底層是陣列。資料讀寫是通過buffer。可以使用方法flip切換讀寫。
public class BufferNio { public static void main(String[] args) { //建立buffer容量為5個int IntBuffer buffer = IntBuffer.allocate(5); //放資料 buffer.put(1); buffer.put(2); buffer.put(3); buffer.put(4); buffer.put(5); //讀寫切換 buffer.flip(); //取資料 //內部維護一個索引,每次get索引都會往後邊移動 while(buffer.hasRemaining()){ System.out.println(buffer.get()); } } }
// Invariants: mark <= position <= limit <= capacity private int mark = -1; private int position = 0; private int limit; private int capacity;
mark:標記,很少改變
position:下一個要被讀元素的位置,為下次讀寫做準備
limit:緩衝器當前的終點,不能對緩衝區極限意外的區域讀寫,可變。
capacity:不可變,建立時指定的最大容量。
上邊出現了讀寫切換的方法flip,我們看下原始碼,可以看出來通過改變屬性實現可讀可寫的。
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
可以通過啊更改limit或者position來實現你想要的操作。引數自己決定
buffer.limit(2); buffer.position(1);
可讀可寫,上接Selector,下連Buffer。
當用戶端連線ServerSocketChannel時,建立使用者端自己的SocketChannel。
public class ChannelNio { public static void main(String[] args) throws IOException { String str = "少壯不努力,老大徒傷悲"; //建立輸出流 FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); //獲取FileChannel FileChannel channel = os.getChannel(); //建立緩衝 ByteBuffer buffer = ByteBuffer.allocate(1024); //把字串放入緩衝區 buffer.put(str.getBytes()); //反轉ByteBuffer buffer.flip(); //將ByteBuffer寫入到FileChannel channel.write(buffer); //關閉流 os.close(); } }
圖示理解
public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); FileChannel channel = is.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer); System.out.println(new String(buffer.array())); is.close(); } }
方法一
public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); FileChannel channel = is.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\b.txt"); FileChannel osChannel = os.getChannel(); while (true){ buffer.clear(); int i = channel.read(buffer); if(i==-1){ break; } buffer.flip(); osChannel.write(buffer); } is.close(); os.close(); } }
方法二
public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\HELP.md"); FileChannel channel = is.getChannel(); FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\HELP222.md"); FileChannel osChannel = os.getChannel(); osChannel.transferFrom(channel,0,channel.size()); is.close(); os.close(); } }
用一個執行緒處理多個使用者端連線。可以檢測多個註冊通道的事件,並作出相應處理。不用維護所有執行緒。
Selector可以獲得被註冊的SocketChannel的一個SelectionKey集合,然後監聽select,獲得有事件發生的SelectionKey,最後通過SelectionKey獲得通道進行相應操作,完成業務。
到此這篇關於Java筆記之從IO模型到Netty框架學習初識篇的文章就介紹到這了,更多相關Java Netty框架內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45