在全部互聯網公司中,Nginx 做爲最經常使用的 7 層負載均衡代理層,每一個後端開發人員和運維人員都應該對其有較爲深刻的理解。java
小編分享的這份金三銀四Java後端開發面試總結包含了JavaOOP、Java集合容器、Java異常、併發編程、Java反射、Java序列化、JVM、Redis、Spring MVC、MyBatis、MySQL數據庫、消息中間件MQ、Dubbo、Linux、ZooKeeper、 分佈式&數據結構與算法等26個專題技術點,都是小編在各個大廠總結出來的面試真題,已經有不少粉絲靠這份PDF拿下衆多大廠的offer,今天在這裏總結分享給到你們!【持續更新中!】面試
完整版Java面試題地址:2021最新面試題合集集錦。算法
序號 | 專題 | 內容 | 連接 |
---|---|---|---|
1 | 中間件 | Java中間件面試題(2021最新版) | https://blog.51cto.com/14994509/2692669 |
2 | 微服務 | Java微服務面試題(2021最新版) | http://www.javashuo.com/article/p-haiifnkb-vk.html |
3 | 併發編程 | Java併發編程面試題(2021最新版) | http://www.javashuo.com/article/p-rirekprn-vk.html |
4 | Java基礎 | Java基礎知識面試題(2021最新版) | https://blog.51cto.com/blogger/success/2706687 |
5 | Spring Boot | Spring Boot面試題(2021最新版) | http://www.javashuo.com/article/p-etpzmprr-vk.html |
6 | Redis | Redis面試題(2021最新版) | http://www.javashuo.com/article/p-adjrmfwe-vk.html |
7 | Spring MVC | Spring MVC面試題(2021最新版) | https://blog.51cto.com/u_14994509/2711562 |
8 | Spring Cloud | Spring Cloud面試題(2021最新版) | http://www.javashuo.com/article/p-emhafwrm-vk.html |
9 | MySQL優化 | MySQL優化面試題(2021最新版) | https://blog.51cto.com/u_14994509/2716504 |
10 | JVM | JVM性能調優面試題(2021最新版) | https://blog.51cto.com/u_14994509/2716514 |
11 | Linux | Linux面試題(2021最新版) | https://blog.51cto.com/u_14994509/2718559 |
12 | Mybatis | Mybatis面試題(2021最新版) | https://blog.51cto.com/u_14994509/2718588 |
13 | 網絡編程 | TCP,UDP,Socket,Http網絡編程面試題(2021最新版) | https://blog.51cto.com/u_14994509/2718599 |
14 | 設計模式 | 設計模式面試題(2021最新版) | https://blog.51cto.com/u_14994509/2735448 |
15 | 大數據 | 大數據面試題100道(2021最新版) | https://blog.51cto.com/u_14994509/2736601 |
16 | Tomcat | Tomcat面試題(2021最新版) | https://blog.51cto.com/u_14994509/2739386 |
17 | 多線程 | 多線程面試題(2021最新版) | https://blog.51cto.com/u_14994509/2739435 |
18 | Nginx | Nginx_BIO_NIO_AIO面試題(2021最新版) | 持續更新中! |
19 | memcache | memcache面試題(2021最新版) | 持續更新中! |
20 | java異常 | java異常面試題(2021最新版) | 持續更新中! |
21 | Java虛擬機 | Java虛擬機面試題(2021最新版) | 持續更新中! |
22 | Java集合 | Java集合面試題(2021最新版) | 持續更新中! |
23 | Git經常使用命令 | Git經常使用命令(2021最新版) | 持續更新中! |
24 | Elasticsearch | Elasticsearch面試題(2021最新版) | 持續更新中! |
25 | Dubbo | Dubbo面試題(2021最新版) | 持續更新中! |
BIO:同步並阻塞,服務器實現一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,沒處理完以前此線程不能作其餘操做(若是是單線程的狀況下,我傳輸的文件很大呢?),固然能夠經過線程池機制改善。BIO方式適用於鏈接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4之前的惟一選擇,但程序直觀簡單易理解。數據庫
NIO:同步非阻塞,服務器實現一個鏈接一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4以後開始支持。 編程
注意:我這裏的用戶空間就是應用程序空間 後端
B也在河邊釣魚,可是B不想將本身的全部時間都花費在釣魚上,在等魚上鉤這個時間段中,B也在作其餘的事情(一會看看書,一會讀讀報紙,一會又去看其餘人的釣魚等),但B在作這些事情的時候,每隔一個固定的時間檢查魚是否上鉤。一旦檢查到有魚上鉤,就停下手中的事情,把魚釣上來。 B在檢查魚竿是否有魚,是一個輪詢的過程。設計模式
G也在河邊釣魚,但與A、B、C不一樣的是,G比較聰明,他給魚竿上掛一個鈴鐺,當有魚上鉤的時候,這個鈴鐺就會被碰響,G就會將魚釣上來。 api
屬於處理流中的緩衝流,能夠將讀取的內容存在內存裏面,有readLine()方法數組
這裏的基本操做就是普通的讀取操做,若是想要跟深刻的瞭解不一樣的IO開發場景必須先了解IO的基本操做服務器
package com.test.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; //TCP協議Socket使用BIO進行通訊:服務端 public class BIOServer { // 在main線程中執行下面這些代碼 public static void main(String[] args) { //使用Socket進行網絡通訊 ServerSocket server = null; Socket socket = null; //基於字節流 InputStream in = null; OutputStream out = null; try { server = new ServerSocket(8000); System.out.println("服務端啓動成功,監聽端口爲8000,等待客戶端鏈接..."); while (true){ socket = server.accept(); //等待客戶端鏈接 System.out.println("客戶鏈接成功,客戶信息爲:" + socket.getRemoteSocketAddress()); in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; //讀取客戶端的數據 while ((len = in.read(buffer)) > 0) { System.out.println(new String(buffer, 0, len)); } //向客戶端寫數據 out = socket.getOutputStream(); out.write("hello!".getBytes()); } } catch (IOException e) { e.printStackTrace(); } } } TCP協議Socket使用BIO進行通訊:客戶端(第二執行) package com.test.io; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; //TCP協議Socket使用BIO進行通訊:客戶端 public class Client01 { public static void main(String[] args) throws IOException { //建立套接字對象socket並封裝ip與port Socket socket = new Socket("127.0.0.1", 8000); //根據建立的socket對象得到一個輸出流 //基於字節流 OutputStream outputStream = socket.getOutputStream(); //控制檯輸入以IO的形式發送到服務器 System.out.println("TCP鏈接成功 \n請輸入:"); String str = new Scanner(System.in).nextLine(); byte[] car = str.getBytes(); outputStream.write(car); System.out.println("TCP協議的Socket發送成功"); //刷新緩衝區 outputStream.flush(); //關閉鏈接 socket.close(); } } package com.test.io; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; //TCP協議Socket:客戶端 public class Client02 { public static void main(String[] args) throws IOException { //建立套接字對象socket並封裝ip與port Socket socket = new Socket("127.0.0.1", 8000); //根據建立的socket對象得到一個輸出流 //基於字節流 OutputStream outputStream = socket.getOutputStream(); //控制檯輸入以IO的形式發送到服務器 System.out.println("TCP鏈接成功 \n請輸入:"); String str = new Scanner(System.in).nextLine(); byte[] car = str.getBytes(); outputStream.write(car); System.out.println("TCP協議的Socket發送成功"); //刷新緩衝區 outputStream.flush(); //關閉鏈接 socket.close(); } }
這時有人就會說,我多線程不就解決了嗎?
package com.test.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; //TCP協議Socket使用多線程BIO進行通行:服務端 public class BIOThreadService { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(8000); System.out.println("服務端啓動成功,監聽端口爲8000,等待客戶端鏈接... "); while (true) { Socket socket = server.accept();//等待客戶鏈接 System.out.println("客戶鏈接成功,客戶信息爲:" + socket.getRemoteSocketAddress()); //針對每一個鏈接建立一個線程, 去處理I0操做 //建立多線程建立開始 Thread thread = new Thread(new Runnable() { public void run() { try { InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; //讀取客戶端的數據 while ((len = in.read(buffer)) > 0) { System.out.println(new String(buffer, 0, len)); } //向客戶端寫數據 OutputStream out = socket.getOutputStream(); out.write("hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } } }); thread.start(); } } catch (IOException e) { e.printStackTrace(); } } }
package com.test.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //TCP協議Socket使用線程池BIO進行通行:服務端 public class BIOThreadPoolService { public static void main(String[] args) { //建立線程池 ExecutorService executorService = Executors.newFixedThreadPool(30); try { ServerSocket server = new ServerSocket(8000); System.out.println("服務端啓動成功,監聽端口爲8000,等待客戶端鏈接..."); while (true) { Socket socket = server.accept(); //等待客戶鏈接 System.out.println("客戶鏈接成功,客戶信息爲:" + socket.getRemoteSocketAddress()); //使用線程池中的線程去執行每一個對應的任務 executorService.execute(new Thread(new Runnable() { public void run() { try { InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; //讀取客戶端的數據 while ((len = in.read(buffer)) > 0) { System.out.println(new String(buffer, 0, len)); } //向客戶端寫數據 OutputStream out = socket.getOutputStream(); out.write("hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } } } ) ); } } catch (IOException e) { e.printStackTrace(); } } }
package com.test.io; import com.lijie.iob.RequestHandler; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class NIOServer { public static void main(String[] args) throws IOException { //111111111 //Service端的Channel,監聽端口的 ServerSocketChannel serverChannel = ServerSocketChannel.open(); //設置爲非阻塞 serverChannel.configureBlocking(false); //nio的api規定這樣賦值端口 serverChannel.bind(new InetSocketAddress(8000)); //顯示Channel是否已經啓動成功,包括綁定在哪一個地址上 System.out.println("服務端啓動成功,監聽端口爲8000,等待客戶端鏈接..."+ serverChannel.getLocalAddress()); //22222222 //聲明selector選擇器 Selector selector = Selector.open(); //這句話的含義,是把selector註冊到Channel上面, //每一個客戶端來了以後,就把客戶端註冊到Selector選擇器上,默認狀態是Accepted serverChannel.register(selector, SelectionKey.OP_ACCEPT); //33333333 //建立buffer緩衝區,聲明大小是1024,底層使用數組來實現的 ByteBuffer buffer = ByteBuffer.allocate(1024); RequestHandler requestHandler = new RequestHandler(); //444444444 //輪詢,服務端不斷輪詢,等待客戶端的鏈接 //若是有客戶端輪詢上來就取出對應的Channel,沒有就一直輪詢 while (true) { int select = selector.select(); if (select == 0) { continue; } //有可能有不少,使用Set保存Channel Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //使用SelectionKey來獲取鏈接了客戶端和服務端的Channel SelectionKey key = iterator.next(); //判斷SelectionKey中的Channel狀態如何,若是是OP_ACCEPT就進入 if (key.isAcceptable()) { //從判斷SelectionKey中取出Channel ServerSocketChannel channel = (ServerSocketChannel) key.channel(); //拿到對應客戶端的Channel SocketChannel clientChannel = channel.accept(); //把客戶端的Channel打印出來 System.out.println("客戶端通道信息打印:" + clientChannel.getRemoteAddress()); //設置客戶端的Channel設置爲非阻塞 clientChannel.configureBlocking(false); //操做完了改變SelectionKey中的Channel的狀態OP_READ clientChannel.register(selector, SelectionKey.OP_READ); } //到此輪訓到的時候,發現狀態是read,開始進行數據交互 if (key.isReadable()) { //以buffer做爲數據橋樑 SocketChannel channel = (SocketChannel) key.channel(); //數據要想讀要先寫,必須先讀取到buffer裏面進行操做 channel.read(buffer); //進行讀取 String request = new String(buffer.array()).trim(); buffer.clear(); //進行打印buffer中的數據 System.out.println(String.format("客戶端發來的消息: %s : %s", channel.getRemoteAddress(), request)); //要返回數據的話也要先返回buffer裏面進行返回 String response = requestHandler.handle(request); //而後返回出去 channel.write(ByteBuffer.wrap(response.getBytes())); } iterator.remove(); } } } }
package com.test.io; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; //TCP協議Socket:客戶端 public class Client01 { public static void main(String[] args) throws IOException { //建立套接字對象socket並封裝ip與port Socket socket = new Socket("127.0.0.1", 8000); //根據建立的socket對象得到一個輸出流 OutputStream outputStream = socket.getOutputStream(); //控制檯輸入以IO的形式發送到服務器 System.out.println("TCP鏈接成功 n請輸入:"); while(true){ byte[] car = new Scanner(System.in).nextLine().getBytes(); outputStream.write(car); System.out.println("TCP協議的Socket發送成功"); //刷新緩衝區 outputStream.flush(); } } }