在全部互联网公司中,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(); } } }