Netty权威指南之伪异步I/O编程
為了解決同步阻塞I/O一個鏈路需要一個線程處理問題,對BIO模型做了優(yōu)化——后端通過一個線程池處理多個客戶端的請求接入,設(shè)置線程最大值,防止線程并發(fā)接入導(dǎo)致的線程耗盡。
當(dāng)有新的客戶端接入時,將客戶端Socket封裝成一個Task(該任務(wù)實(shí)現(xiàn)java.lang.Runnable接口)投遞到后端的線程池中進(jìn)行處理,JDK的線程池維護(hù)一個消息隊(duì)列和N個活躍線程,對消息隊(duì)列中的任務(wù)進(jìn)行處理。由于線程池可以設(shè)置消息隊(duì)列的大小和最大線程數(shù),因此資源占用是可控的,無論多少客戶端并發(fā)訪問都不會導(dǎo)致資源耗盡和宕機(jī)。
偽異步I/O通信框架采用了線程池實(shí)現(xiàn),避免了每次請求創(chuàng)建一個獨(dú)立的線程造成的資源耗盡問題,底層通信依然采用BIO同步阻塞模型,無法從根本上解決問題。當(dāng)對方發(fā)送請求或者應(yīng)答消息比較緩慢(如數(shù)據(jù)大),或者網(wǎng)路傳輸較慢時(網(wǎng)速差)讀取輸入流一方的通信線程將被長時間阻塞,阻塞期間,其他接入消息只能在消息隊(duì)列中排隊(duì)。阻塞結(jié)束情況:1)有數(shù)據(jù)可讀,2)可用數(shù)據(jù)已經(jīng)讀取完畢,3)發(fā)生空指針或IO異常
package com.hjp.netty.pseudoasynio;import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;public class TimeServerHandlerExecutePool {private ExecutorService executor;public TimeServerHandlerExecutePool(int maxPoolSize, int queueSize) {executor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));}public void execute(Runnable task) {executor.execute(task);}} 線程池處理類 package com.hjp.netty.pseudoasynio;import sun.awt.windows.ThemeReader;import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;public class TimeServer {public static void main(String[] args) throws IOException {int port = 8080;if (args != null && args.length > 0) {try {port = Integer.valueOf(port);} catch (NumberFormatException e) {e.printStackTrace();}}ServerSocket server = null;try {server = new ServerSocket(port);System.out.println("The time server is start in port : " + port);Socket socket = null;TimeServerHandlerExecutePool singleExecutor = new TimeServerHandlerExecutePool(50, 10000);while (true) {socket = server.accept();singleExecutor.execute(new TimeServerHandler(socket));}} finally {if (server != null) {System.out.println("The time server close");server.close();server = null;}}}} TimeServer package com.hjp.netty.pseudoasynio;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Date;public class TimeServerHandler implements Runnable {private Socket socket;public TimeServerHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {BufferedReader in = null;PrintWriter out = null;try {in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));out = new PrintWriter(this.socket.getOutputStream(), true);String currentTime = null;String body = null;while (true) {body = in.readLine();if (body == null) {break;}System.out.println("The time server receive order : " + body);currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";out.println(currentTime);}} catch (Exception e) {if (in != null) {try {in.close();} catch (IOException e1) {e1.printStackTrace();}}if (out != null) {out.close();out = null;}if (this.socket != null) {try {this.socket.close();} catch (IOException e1) {e1.printStackTrace();}this.socket = null;}}} } TimeServerHandler客戶端代碼和BIO客戶端代碼一樣
總結(jié)
以上是生活随笔為你收集整理的Netty权威指南之伪异步I/O编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IE与Chrome对相对URL解析的区别
- 下一篇: Shell字符串处理之 ${}