佛山网站建设优化,网页美工用什么软件,购物网站开发设计类图,西安今晚12点封城吗今天早上关注了这个问题#xff0c;刚抽出时间大概整理下#xff0c;以下仅是个人理解#xff1a;一定要多看几遍代码并结合文字理解下引0、从I/O说起这些概念之所以容易令人迷惑#xff0c;在于很多人对I/O就没有清晰准确的理解#xff0c;后面的理解自然不可能正确。我想…今天早上关注了这个问题刚抽出时间大概整理下以下仅是个人理解一定要多看几遍代码并结合文字理解下引0、从I/O说起这些概念之所以容易令人迷惑在于很多人对I/O就没有清晰准确的理解后面的理解自然不可能正确。我想用一个具体的例子来说明一下I/O。设想自己是一个进程就叫小进吧。小进需要接收一个输入我们不管这个输入是从网络套接字来还是键盘鼠标来输入的来源可以千千万万。但是都必须由内核来帮小进完成为啥内核这么霸道因为计算机上运行的可不只是咱小进一个进程还有很多进程。这些进程兄弟也可能需要从这些输入设备接收输入没有内核居中协调岂不是乱套。从小进的角度看内核帮助它完成输入其实包括三个步骤内核替小进接收好数据这些数据暂时存在内核的内存空间内核将数据从自己的内存空间复制到小进的内存空间告诉小进输入数据来了赶快读吧这三步看似挺简单其实在具体实现时有很多地方需要考虑:小进如何告诉内核自己要接收一个输入内核接到小进的请求替小进接收好数据这段时间 小进咋办内核在将数据复制到小进的内存空间这段时间小进咋办到底什么时候告诉小进数据准备好了是在内核接收好数据之后就告诉小进还是在将数据复制到小进的内存空间之后再告诉他内核以什么样的方式告诉小进数据准备好了1、阻塞式I/O模型对上面5个问题最简单的解决方案就是阻塞式I/O模型它的过程是这样的小进内核内核我要接收一个键盘输入快点帮我完成内核好咧biubiu一个阻塞丢给小进小进顿时石化就像被孙悟空点了定一样。就这样小进在石化中时间一点点流逝。终于内核收到了数据。内核数据终于来了我要开干了duang duang duang先把数据存在自己的内核空间然后又复制到小进的用户空间。内核biubiu一个解除阻塞丢给小进小进瞬间复活小进的记忆还是停留在让内核帮他接收输入时。小进哇内核真靠谱数据已经有了干活去我们可以看到小进发出接收输入的请求给内核开始就处于阻塞状态直到内核将数据复制到小进的用户空间小进才解除阻塞。2、非阻塞式I/O小进发现阻塞式I/O中自己总要被阻塞好久好不爽啊于是小进改用了非阻塞式I/O其过程是这样的小进内核内核我要接收一个输入赶紧帮我看看数据到了没有先说好不要阻塞我。内核查看了一下自己的内核空间没有发现数据于是迅速告诉小进没有呢并继续帮小进等着数据。如此这样小进不断地问内核终于过了一段时间小进再一次询问时内核往自己的空间中一查呦数据来了不胜其烦的内核迅速告诉小进数据好了小进快给我内核biu一个阻塞丢给小进悲催的小进还是石化了内核赶紧将自己空间的输入数据复制到小进的用户空间复制好后。内核biu一个非阻塞丢给小进小进立马复活小进哇数据来了啥也不说干活我们看到所谓的非阻塞I/O其实在内核将数据从内核空间复制到小进的用户空间时小进还是被阻塞的。3、信号驱动式I/O非阻塞I/O中小进不停地问内核数据好了没有啊内核感觉太烦了于是想出一个好办法。内核告诉小进本内核升级了如果想要我替你接收输入请先注册一个信号处理函数等数据准备好时我会发信号给你。于是现在的流程是这样的小进注册信号处理函数告诉内核自己要接收一个输入然后继续干活内核收到函数开始执行数据接收接收完成时给小进发送信号信号处理函数收到信号开始向内核发送读数据请求内核biu阻塞了小进并把数据从内核空间复制到小进的用户空间。内核biu解除了阻塞小进哇数据来了啥也不说干活去4、异步I/O上面的三种I/O解决方案中小进都被阻塞了只不过是阻塞时间长短不一样第一种方案中小进被阻塞的时间长一些在内核接收数据以及将数据复制到小进的用户空间时都被阻塞。第二、第三种方案中只在内核将数据从内核空间复制到小进的用户空间时小进才被阻塞。我们现在说的异步I/O目的就是让小进绝对不被阻塞。其过程是这样的小进内核内核我要接收一个输入弄好了告诉我。同时将一个信号和信号处理函数告诉内核然后继续干自己的活了。内核得了您嘞您先忙。一直到内核接收到数据并将数据从内核空间复制到小进的用户空间后内核才给小进发送信号。小进在信号处理函数中可以直接处理数据。践1、阻塞式I/O式客户端代码public class Client {public static void main(String[] args) {Socket socket null;try {System.out.println(socket begin System.currentTimeMillis());// 随机绑定本地地址与端口socket new Socket(localhost, 8888);System.out.println(socket end System.currentTimeMillis());OutputStream os socket.getOutputStream();Random ran new Random();for (int n 0; n 10; n) {System.out.println(send message n);os.write((hello server form socket.getLocalAddress().getHostAddress() - n).getBytes());try {TimeUnit.SECONDS.sleep(ran.nextInt(10));} catch (InterruptedException e) {break;}}} catch (IOException e) {e.printStackTrace();} finally {try {if (socket ! null) {// 自动关闭绑定流socket.close();}System.out.println(exit);} catch (IOException e) {e.printStackTrace();}}}}服务端代码public class Server {public static void main(String[] args) {ServerSocket serverSocket null;Socket socket null;ThreadPoolExecutor executor null;try {// 初始化线程池executor new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),Runtime.getRuntime().availableProcessors() * 2,0L, TimeUnit.SECONDS, new LinkedBlockingDeque(), new ThreadBuilder());// 监听通配符地址serverSocket new ServerSocket(8888);System.out.println(accept begin System.currentTimeMillis());while ((socket serverSocket.accept()) ! null) {executor.execute(new Task(socket));}System.out.println(accept end System.currentTimeMillis());} catch (IOException e) {e.printStackTrace();} finally {executor.shutdown();try {if (serverSocket ! null) {serverSocket.close();}System.out.println(exit);} catch (IOException e) {e.printStackTrace();}}}static class ThreadBuilder implements ThreadFactory {private AtomicInteger counter new AtomicInteger(0);Overridepublic Thread newThread(Runnable r) {Thread thread new Thread(r, server-thread- counter.getAndIncrement());thread.setUncaughtExceptionHandler((t, e) - {if (e instanceof TaskException) {System.err.println(t.getName() | e.getCause().getMessage());} else {System.err.println(t.getName() | e.getMessage());}});return thread;}}static class Task implements Runnable {private byte[] buffer new byte[10 * 1024];private Socket socket;public Task(Socket socket) {this.socket socket;}Overridepublic void run() {try {InputStream is socket.getInputStream();System.out.println(--------------------------------------------------);System.out.println(read begin System.currentTimeMillis());System.out.println(***);int len is.read(buffer);// 呈阻塞效果while (len ! -1) {String str new String(buffer, 0, len);System.out.println(str);len is.read(buffer);}System.out.println(***);System.out.println(read end System.currentTimeMillis());System.out.println(--------------------------------------------------);} catch (IOException e) {throw new TaskException(e);} finally {if (socket ! null) {try {// 自动关闭绑定流socket.close();System.out.println(socket closed);} catch (IOException e) {System.err.println(socket close failed);}}}}}static class TaskException extends RuntimeException {public TaskException(Throwable cause) {super(cause);}}}2、非阻塞式I/O客户端代码同上服务端代码public class Server {public static void main(String[] args) {ServerSocketChannel serverSocket null;SocketChannel socket null;ThreadPoolExecutor executor null;try {// 初始化线程池executor new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),Runtime.getRuntime().availableProcessors() * 2,0L, TimeUnit.SECONDS, new LinkedBlockingDeque(), new ThreadBuilder());serverSocket ServerSocketChannel.open();// 设置阻塞serverSocket.configureBlocking(true);// 监听通配符地址serverSocket.bind(new InetSocketAddress(8888));System.out.println(accept begin System.currentTimeMillis());while ((socket serverSocket.accept()) ! null) {// 设置非阻塞socket.configureBlocking(false);executor.execute(new Task(socket));}System.out.println(accept end System.currentTimeMillis());} catch (IOException e) {e.printStackTrace();} finally {executor.shutdown();try {if (serverSocket ! null) {serverSocket.close();}System.out.println(exit);} catch (IOException e) {e.printStackTrace();}}}static class ThreadBuilder implements ThreadFactory {private AtomicInteger counter new AtomicInteger(0);Overridepublic Thread newThread(Runnable r) {Thread thread new Thread(r, server-thread- counter.getAndIncrement());thread.setUncaughtExceptionHandler((t, e) - {if (e instanceof TaskException) {System.err.println(t.getName() | e.getCause().getMessage());} else {System.err.println(t.getName() | e.getMessage());}});return thread;}}static class Task implements Runnable {private ByteBuffer buffer ByteBuffer.allocate(10 * 1024);private SocketChannel socket;public Task(SocketChannel socket) {this.socket socket;}Overridepublic void run() {try {System.out.println(--------------------------------------------------);System.out.println(read begin System.currentTimeMillis());System.out.println(***);socket.read(buffer);// 呈阻塞效果while (true) {if (buffer.position() 0) {try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {continue;}} else {buffer.flip();String str new String(buffer.array(), 0, buffer.limit());System.out.println(str);if (exit.equals(str)) {break;}buffer.clear();}socket.read(buffer);}System.out.println(***);System.out.println(read end System.currentTimeMillis());System.out.println(--------------------------------------------------);} catch (IOException e) {throw new TaskException(e);} finally {if (socket ! null) {try {// 自动关闭绑定流socket.close();System.out.println(socket closed);} catch (IOException e) {System.err.println(socket close failed);}}}}}static class TaskException extends RuntimeException {public TaskException(Throwable cause) {super(cause);}}}3、多路复用式I/O(基于非阻塞式I/O)客户端代码同上服务端代码public class Server {public static void main(String[] args) {Selector selector null;ServerSocketChannel serverSocket null;SocketChannel socket null;ThreadPoolExecutor executor null;try {// 初始化线程池executor new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),Runtime.getRuntime().availableProcessors() * 2,0L, TimeUnit.SECONDS, new LinkedBlockingDeque(), new ThreadBuilder());selector Selector.open();serverSocket ServerSocketChannel.open();// 设置非阻塞serverSocket.configureBlocking(false);// 监听通配符地址serverSocket.bind(new InetSocketAddress(8888));serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println(accept begin System.currentTimeMillis());while (true) {selector.select();Iterator iterator selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey key iterator.next();if (key.isAcceptable()) {ServerSocketChannel serverSocketChannel (ServerSocketChannel) key.channel();SocketChannel socketChannel serverSocketChannel.accept();// 设置非阻塞socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel socketChannel (SocketChannel) key.channel();executor.execute(new Task(socketChannel));key.cancel();} else {// TODO 写事件注册}iterator.remove();}}// System.out.println(accept end System.currentTimeMillis());} catch (IOException e) {e.printStackTrace();} finally {executor.shutdown();try {if (serverSocket ! null) {serverSocket.close();}System.out.println(exit);} catch (IOException e) {e.printStackTrace();}}}static class ThreadBuilder implements ThreadFactory {private AtomicInteger counter new AtomicInteger(0);Overridepublic Thread newThread(Runnable r) {Thread thread new Thread(r, server-thread- counter.getAndIncrement());thread.setUncaughtExceptionHandler((t, e) - {if (e instanceof TaskException) {System.err.println(t.getName() | e.getCause().getMessage());} else {System.err.println(t.getName() | e.getMessage());}});return thread;}}static class Task implements Runnable {private ByteBuffer buffer ByteBuffer.allocate(10 * 1024);private SocketChannel socket;public Task(SocketChannel socket) {this.socket socket;}Overridepublic void run() {try {System.out.println(--------------------------------------------------);System.out.println(read begin System.currentTimeMillis());System.out.println(***);socket.read(buffer);// 呈阻塞效果while (true) {if (buffer.position() 0) {try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {continue;}} else {buffer.flip();String str new String(buffer.array(), 0, buffer.limit());System.out.println(str);if (exit.equals(str)) {break;}buffer.clear();}socket.read(buffer);}System.out.println(***);System.out.println(read end System.currentTimeMillis());System.out.println(--------------------------------------------------);} catch (IOException e) {throw new TaskException(e);} finally {if (socket ! null) {try {// 自动关闭绑定流socket.close();System.out.println(socket closed);} catch (IOException e) {System.err.println(socket close failed);}}}}}static class TaskException extends RuntimeException {public TaskException(Throwable cause) {super(cause);}}}4、信号驱动式I/OJAVA没有实现5、异步I/O客户端代码同上服务端代码public class Server {public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {AsynchronousServerSocketChannel serverSocketChannel AsynchronousServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(8888));serverSocketChannel.accept(null, new CompletionHandler() {public void completed(AsynchronousSocketChannel asc, Void att) {serverSocketChannel.accept(null, this);ByteBuffer byteBuffer ByteBuffer.allocate(10 * 1024);asc.read(byteBuffer, null, new CompletionHandler() {Overridepublic void completed(Integer result, Void attachment) {byteBuffer.flip();System.out.println(new String(byteBuffer.array(), 0, byteBuffer.limit()));byteBuffer.clear();try {asc.close();} catch (IOException e) {}}Overridepublic void failed(Throwable exc, Void attachment) {}});}public void failed(Throwable exc, Void att) {}});for (; ; ) {}}}结牛奶工送牛奶场景阻塞式每天早上自己去小区门口等牛奶工非阻塞式每天早上在家从窗户早上隔3分钟看看牛奶工到了没到了的话去拿多路复用式每天早上由小区门卫室接待所有牛奶工到了会给住户发短信你马上去拿信号驱动式每天早上牛奶工到了会给你发短信你马上去拿异步式每天早上牛奶工直接放到小区住户牛奶柜并发短信不需要现在去拿它程序分为CPU计算型和I/O读写型线程尤其是被内核调度的线程是及其珍贵的资源(JAVA计划在JDK将来的版本实现由JVM”自己“调度的轻型线程)在有限的线程资源下CPU计算型程序不但不会有明显提升反而由于频繁的上下文切换导致性能下降(这也是Redis这种基于内存的数据库采用单工作线程并且速度非常快的原因另一个重要的原因是单线程导致了不用为共享资源给线程加/解锁造成人为阻塞)而在I/O读写型的程序中多线程工作在以上五种模式下性能是逐步提升的(最后多说一句还是以Redis举例不管是Jedis-Pool这种池化客户端还是Lettuce这种单连接客户端当多用户接入Redis服务器时一定是多连接的这时候就要用到多路复用来处理用户请求了至于为什么没有用异步一个原因是工作线程是单线程另一个原因是异步I/O模型在性能提升方面有限并且复杂度高以至于Netty在新版本的包中把这种模式删除了)