- 浏览: 48304 次
- 性别:
- 来自: 广州
最新评论
-
winmap:
import jnative.wrapper.JnaWrapp ...
jnative callback 回调函数的实现 -
lfpzln:
<div class="quote_title ...
解读NIO Socket非阻塞模式 -
chenjunt3:
chenjunt3@163.com 谢谢!!
集成了一个框架(jdbc封装) -
ljz0898:
你好 能否提供一些源码 谢谢 549070343@qq.co ...
集成了一个框架(jdbc封装) -
沙洲胡杨:
您好,能给我发份源码吗?lbj2011@163.com
集成了一个框架(jdbc封装)
前言:
jdk供的无阻塞I/O(NIO)有效解决了多线程服务器存在的线程开销问题,但在使用上略显得复杂一些。在NIO中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个CPU的处理能力和处理中的等待时间,达到提高服务能力的目的。
这段时间在研究NIO,写篇博客来记住学过的东西。还是从最简单的Hello World开始,
client多线程请求server端,server接收client的名字,并返回Hello! +名字的字符格式给client。当然实际应用并不这么简单,实际可能是访问文件或者数据库获取信息返回给client。非阻塞的NIO有何神秘之处?代码:
1)server端代码
/** * * @author Jeff * */ public class HelloWorldServer { static int BLOCK = 1024; static String name = ""; protected Selector selector; protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK); protected CharsetDecoder decoder; static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder(); public HelloWorldServer(int port) throws IOException { selector = this.getSelector(port); Charset charset = Charset.forName("GB2312"); decoder = charset.newDecoder(); } // 获取Selector protected Selector getSelector(int port) throws IOException { ServerSocketChannel server = ServerSocketChannel.open(); Selector sel = Selector.open(); server.socket().bind(new InetSocketAddress(port)); server.configureBlocking(false); server.register(sel, SelectionKey.OP_ACCEPT); return sel; } // 监听端口 public void listen() { try { for (;;) { selector.select(); Iterator iter = selector.selectedKeys().iterator(); while (iter.hasNext()) { SelectionKey key = (SelectionKey) iter.next(); iter.remove(); process(key); } } } catch (IOException e) { e.printStackTrace(); } } // 处理事件 protected void process(SelectionKey key) throws IOException { if (key.isAcceptable()) { // 接收请求 ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel channel = server.accept(); //设置非阻塞模式 channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { // 读信息 SocketChannel channel = (SocketChannel) key.channel(); int count = channel.read(clientBuffer); if (count > 0) { clientBuffer.flip(); CharBuffer charBuffer = decoder.decode(clientBuffer); name = charBuffer.toString(); // System.out.println(name); SelectionKey sKey = channel.register(selector, SelectionKey.OP_WRITE); sKey.attach(name); } else { channel.close(); } clientBuffer.clear(); } else if (key.isWritable()) { // 写事件 SocketChannel channel = (SocketChannel) key.channel(); String name = (String) key.attachment(); ByteBuffer block = encoder.encode(CharBuffer .wrap("Hello !" + name)); channel.write(block); //channel.close(); } } public static void main(String[] args) { int port = 8888; try { HelloWorldServer server = new HelloWorldServer(port); System.out.println("listening on " + port); server.listen(); } catch (IOException e) { e.printStackTrace(); } } }
server主要是读取client发过来的信息,并返回一条信息
2)client端代码
/** * * @author Jeff * */ public class HelloWorldClient { static int SIZE = 10; static InetSocketAddress ip = new InetSocketAddress("localhost", 8888); static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder(); static class Message implements Runnable { protected String name; String msg = ""; public Message(String index) { this.name = index; } public void run() { try { long start = System.currentTimeMillis(); //打开Socket通道 SocketChannel client = SocketChannel.open(); //设置为非阻塞模式 client.configureBlocking(false); //打开选择器 Selector selector = Selector.open(); //注册连接服务端socket动作 client.register(selector, SelectionKey.OP_CONNECT); //连接 client.connect(ip); //分配内存 ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); int total = 0; _FOR: for (;;) { selector.select(); Iterator iter = selector.selectedKeys().iterator(); while (iter.hasNext()) { SelectionKey key = (SelectionKey) iter.next(); iter.remove(); if (key.isConnectable()) { SocketChannel channel = (SocketChannel) key .channel(); if (channel.isConnectionPending()) channel.finishConnect(); channel .write(encoder .encode(CharBuffer.wrap(name))); channel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel channel = (SocketChannel) key .channel(); int count = channel.read(buffer); if (count > 0) { total += count; buffer.flip(); while (buffer.remaining() > 0) { byte b = buffer.get(); msg += (char) b; } buffer.clear(); } else { client.close(); break _FOR; } } } } double last = (System.currentTimeMillis() - start) * 1.0 / 1000; System.out.println(msg + "used time :" + last + "s."); msg = ""; } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { String names[] = new String[SIZE]; for (int index = 0; index < SIZE; index++) { names[index] = "jeff[" + index + "]"; new Thread(new Message(names[index])).start(); } } }
评论
28 楼
lfpzln
2012-02-20
only_java 写道
发现用户NIO发数据,收到的数据是连在一起的。比如
我发两条hello world,然后在服务端接受时则是一下将两条当作一条接受了。这种问题怎么处理呢?
我发两条hello world,然后在服务端接受时则是一下将两条当作一条接受了。这种问题怎么处理呢?
27 楼
Mic_X
2011-07-27
fly_hyp 写道
代码质量非常高,受益匪浅
break _FOR
这质量叫高?
26 楼
only_java
2009-09-03
发现用户NIO发数据,收到的数据是连在一起的。比如
我发两条hello world,然后在服务端接受时则是一下将两条当作一条接受了。这种问题怎么处理呢?
我发两条hello world,然后在服务端接受时则是一下将两条当作一条接受了。这种问题怎么处理呢?
25 楼
sandssss
2009-08-24
<div class="quote_title">pandonix 写道</div>
<div class="quote_div">
<div class="quote_title">sdh5724 写道</div>
<div class="quote_div">
<div class="quote_title">dennis_zane 写道</div>
<div class="quote_div">
<div class="quote_title">cheaper 写道</div>
<div class="quote_div">一个channel有99.9%的几率都是可写的 </div>
<br>这种无厘头的结论不知道你是怎么得出来的</div>
<br><br><br>他是没有写的数据, 也是selector,因此有了此结论, 根本没有理解注册事件的含义。 我开始不懂的时候也碰到过, 你把可写的事件注册了, 那么selector会一直告诉你可写。 然后就是无限循环了。因此, 数据写完了, 你要把写事件从selector里删除了。 不然有的是苦头。</div>
<br><br>貌似LZ数据写完以后,就是没有将OP_WRITE注销掉。不知是否我看错了? <br><pre name="code" class="java"># // 处理事件
# protected void process(SelectionKey key) throws IOException {
# if (key.isAcceptable()) { // 接收请求
# ServerSocketChannel server = (ServerSocketChannel) key.channel();
# SocketChannel channel = server.accept();
# //设置非阻塞模式
# channel.configureBlocking(false);
# channel.register(selector, SelectionKey.OP_READ);
# } else if (key.isReadable()) { // 读信息
# SocketChannel channel = (SocketChannel) key.channel();
# int count = channel.read(clientBuffer);
# if (count > 0) {
# clientBuffer.flip();
# CharBuffer charBuffer = decoder.decode(clientBuffer);
# name = charBuffer.toString();
# // System.out.println(name);
# SelectionKey sKey = channel.register(selector,
# SelectionKey.OP_WRITE);
# sKey.attach(name);
# } else {
# channel.close();
# }
#
# clientBuffer.clear();
# } else if (key.isWritable()) { // 写事件
# SocketChannel channel = (SocketChannel) key.channel();
# String name = (String) key.attachment();
#
# ByteBuffer block = encoder.encode(CharBuffer
# .wrap("Hello !" + name));
#
#
# channel.write(block);
#
# //channel.close();
#
# }
# } </pre>
之前的
<pre name="code" class="java"> while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
process(key);
} </pre>
应该就已经把它remove掉了吧。<br>
</div>
<p> </p>
<p> </p>
<div class="quote_div">
<div class="quote_title">sdh5724 写道</div>
<div class="quote_div">
<div class="quote_title">dennis_zane 写道</div>
<div class="quote_div">
<div class="quote_title">cheaper 写道</div>
<div class="quote_div">一个channel有99.9%的几率都是可写的 </div>
<br>这种无厘头的结论不知道你是怎么得出来的</div>
<br><br><br>他是没有写的数据, 也是selector,因此有了此结论, 根本没有理解注册事件的含义。 我开始不懂的时候也碰到过, 你把可写的事件注册了, 那么selector会一直告诉你可写。 然后就是无限循环了。因此, 数据写完了, 你要把写事件从selector里删除了。 不然有的是苦头。</div>
<br><br>貌似LZ数据写完以后,就是没有将OP_WRITE注销掉。不知是否我看错了? <br><pre name="code" class="java"># // 处理事件
# protected void process(SelectionKey key) throws IOException {
# if (key.isAcceptable()) { // 接收请求
# ServerSocketChannel server = (ServerSocketChannel) key.channel();
# SocketChannel channel = server.accept();
# //设置非阻塞模式
# channel.configureBlocking(false);
# channel.register(selector, SelectionKey.OP_READ);
# } else if (key.isReadable()) { // 读信息
# SocketChannel channel = (SocketChannel) key.channel();
# int count = channel.read(clientBuffer);
# if (count > 0) {
# clientBuffer.flip();
# CharBuffer charBuffer = decoder.decode(clientBuffer);
# name = charBuffer.toString();
# // System.out.println(name);
# SelectionKey sKey = channel.register(selector,
# SelectionKey.OP_WRITE);
# sKey.attach(name);
# } else {
# channel.close();
# }
#
# clientBuffer.clear();
# } else if (key.isWritable()) { // 写事件
# SocketChannel channel = (SocketChannel) key.channel();
# String name = (String) key.attachment();
#
# ByteBuffer block = encoder.encode(CharBuffer
# .wrap("Hello !" + name));
#
#
# channel.write(block);
#
# //channel.close();
#
# }
# } </pre>
之前的
<pre name="code" class="java"> while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
process(key);
} </pre>
应该就已经把它remove掉了吧。<br>
</div>
<p> </p>
<p> </p>
24 楼
mgoann
2009-08-22
我以前也用过NIO,对1000多个gmail帐户轮询,连接到gmail服务器,再注册到select中读事件,这边就有问题了,gmail对连接数没有限制,至少我同时连1000帐号上去没问题,可是对每个帐号的连接时间做了限制,连接超过1小时,gmail会主动断掉连接,并且没有任何效应!
这个时间会发生断掉的连接注册在select中,而且永远都不会有事件触发的机会给你,让你清掉死掉的连接!
请问这个怎么处理?
这个时间会发生断掉的连接注册在select中,而且永远都不会有事件触发的机会给你,让你清掉死掉的连接!
请问这个怎么处理?
23 楼
vivaxiaohua
2009-08-14
就是Observer模式么
22 楼
lqql
2009-06-12
java.lang.Object 写道
maoxiaolu2000 写道
我发现这种nio在长连接的情况下的设计真的很复杂, 要处理几种情况
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
像这种情况还是用Socket更方便一些,用NIO就很麻烦了
这个..........差不多
21 楼
java.lang.Object
2009-06-12
maoxiaolu2000 写道
我发现这种nio在长连接的情况下的设计真的很复杂, 要处理几种情况
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
像这种情况还是用Socket更方便一些,用NIO就很麻烦了
20 楼
lqql
2009-06-10
楼主的只是解决的NIO方式调用,网上这样的例子很多.实际上会有多线程并发的处理.因为监听的线程不能和业务线程串在一起!
19 楼
lirenjiede
2009-06-10
你那个服务器端一直在给客户端写啊
18 楼
lirenjiede
2009-06-10
我跑着有问题啊
17 楼
unsid
2009-03-16
其实之前我一直用普通IO左异步通讯,是通过客户端向服务器发送一个请求,客户端需要返回值,但是又不是立刻就需要,往往是做:客户端传递一个回调函数给发送程序,发送程序用这个回调函数单起一个线程监听,然后客户端客户做别的事情去了,但是效果不是很理想,因为这种请求一多,创建很多线程,理论上客户端可以去做其他事情,但是实际上客户会发现,点击其他功能响应极其缓慢和不可用没区别....nio是不是本质上并非引入了非阻塞的io方法,而是让开发人员在一个线程里实现非阻塞,这样就真地做到了客户端去做其他事情而没影响了,因为始终是一个线程.
16 楼
maoxiaolu2000
2009-03-09
我发现这种nio在长连接的情况下的设计真的很复杂, 要处理几种情况
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单)
2. 某一用户发了一条信息,需要服务器广播给所有客户端
3. 某一用户发了一条信息, 需要服务器发给指定的几个客户端
4. 用户没有发信息,服务器跟据某些需要主动发给所有客户端信息
5. 用户没有发信息,服务器跟据某些需要主动发给指定的几个客户端信息
6. 用户发了一条信息,服务器只需计算不需反回。
15 楼
bloodrate
2009-03-06
我以前写的非阻塞IO是传递一个回调函数进去,单起一个线程监听IO,主线程作其他的事情去....这样可以么?
14 楼
pandonix
2009-03-06
sdh5724 写道
dennis_zane 写道
cheaper 写道
一个channel有99.9%的几率都是可写的
这种无厘头的结论不知道你是怎么得出来的
他是没有写的数据, 也是selector,因此有了此结论, 根本没有理解注册事件的含义。 我开始不懂的时候也碰到过, 你把可写的事件注册了, 那么selector会一直告诉你可写。 然后就是无限循环了。因此, 数据写完了, 你要把写事件从selector里删除了。 不然有的是苦头。
貌似LZ数据写完以后,就是没有将OP_WRITE注销掉。不知是否我看错了?
# // 处理事件 # protected void process(SelectionKey key) throws IOException { # if (key.isAcceptable()) { // 接收请求 # ServerSocketChannel server = (ServerSocketChannel) key.channel(); # SocketChannel channel = server.accept(); # //设置非阻塞模式 # channel.configureBlocking(false); # channel.register(selector, SelectionKey.OP_READ); # } else if (key.isReadable()) { // 读信息 # SocketChannel channel = (SocketChannel) key.channel(); # int count = channel.read(clientBuffer); # if (count > 0) { # clientBuffer.flip(); # CharBuffer charBuffer = decoder.decode(clientBuffer); # name = charBuffer.toString(); # // System.out.println(name); # SelectionKey sKey = channel.register(selector, # SelectionKey.OP_WRITE); # sKey.attach(name); # } else { # channel.close(); # } # # clientBuffer.clear(); # } else if (key.isWritable()) { // 写事件 # SocketChannel channel = (SocketChannel) key.channel(); # String name = (String) key.attachment(); # # ByteBuffer block = encoder.encode(CharBuffer # .wrap("Hello !" + name)); # # # channel.write(block); # # //channel.close(); # # } # }
13 楼
fjlyxx
2009-03-01
cheaper 写道
一个channel有99.9%的几率都是可写的, 如果selecter一个可写状态会导致cpu使用率很高, 相当的恐怖.
谁叫你注册你不该关系的事件了
12 楼
aninfeel
2009-02-24
刚开始的时候我也很头晕的,过了一个星期才总算接受了这种模式.
11 楼
aninfeel
2009-02-24
刚开始的时候我也很头晕的,过了一个星期才总算接受了这种模式.
10 楼
niveko
2009-02-24
据我所知,nio一般是用在高并发的服务器上,能说说服务器的线程是怎么处理的吗?
9 楼
hbb
2009-02-24
以前写过一个例子,不过遇到这么一个问题:
用telnet连接服务器后,直接关闭窗口,此时连接已经断开,但是服务器端无法判断,此后服务器端就出现一系列的异常。请问这个该怎么解决?
用telnet连接服务器后,直接关闭窗口,此时连接已经断开,但是服务器端无法判断,此后服务器端就出现一系列的异常。请问这个该怎么解决?
发表评论
-
BAT命令详解
2009-01-06 09:44 3984BAT常用命令 echo、@、call、pause、rem(小 ... -
Eclipse常用重要的几个快捷键
2008-12-05 09:21 905编辑相关快捷键 1、〔Alt+/〕 为用户提供 ... -
解读synchronized关键字
2008-11-27 12:04 884最近在写多线程程序,网上收集总结了synchronized的用 ... -
使用异或进行简单的密码加密
2008-11-19 15:05 1984/** * 使用异或进行简单的密码加密 * ... -
Java 中的位运算
2008-11-13 12:46 1971移位运算符 包括: “>> 右移 ... -
解读java.lang.ThreadLocal
2008-10-24 12:52 1324ThreadLocal是什么呢?其实ThreadLocal并非 ... -
Java之Reference
2008-10-24 12:51 988Reference Java世界泰山北 ... -
关于ClassLoader
2008-10-24 12:48 9651,什么是ClassLoader 与 C ... -
解决gwt性能问题
2008-10-24 12:08 2115最近在做gwt的项目时发现,打开第一个页面的速度非常慢, ... -
二进制、八进制、十六进制[转]
2008-06-25 16:56 1790这是一节“前不着村后不着店”的课。不同进制之间的转换纯粹是数学 ... -
16进制和byte之间的关系
2008-06-25 15:20 1791关于byte: signed byte 把 0x00 ~ ... -
字符,字节和编码(很实用的文章 转载)
2008-06-22 11:17 1106引言 “字符与编码”是 ... -
jnative callback 回调函数的实现
2008-06-21 21:48 4620jnative 1.3.2版本发布了,可以完美支持C回 ... -
JPA中的动态查询与指定查询(转载)
2008-01-13 14:41 3227可以使用动态查询或指定查询(named query)。指定查询 ... -
Subversion快速入门教程
2008-01-13 14:37 917如何快速建立Subversion服务器,并且在项目中使用起来, ... -
泛型dao 详细剖析
2008-01-13 14:32 924由于 Java™ 5 泛 ... -
集成了一个框架(jdbc封装)
2007-11-28 17:56 4291...
相关推荐
在Java NIO中,Socket通信可以采用非阻塞模式,允许一个线程处理多个客户端连接,这对于高并发的网络应用尤其有益。 在给定的示例中,`HelloWorldServer`类展示了如何使用NIO创建一个非阻塞的服务器。以下是关键...
jdk供的无阻塞I/O(NIO)有效解决了多线程服务器存在的线程开销问题,但在使用上略显得复杂一些。在NIO中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务...非阻塞的NIO有何神秘之处?直接上代码!
而更高级的socket编程则会使用`java.nio.channels.SocketChannel`和`java.nio.channels.ServerSocketChannel`类,它们支持非阻塞模式和更高效的数据处理方式。 #### 二、非阻塞IO与选择器 传统的IO操作是阻塞式的...
在深入探讨Netty 5.0的架构和源码之前,我们需要先理解NIO(非阻塞I/O)的概念。NIO与传统的阻塞I/O模型不同,它允许多个操作在单个线程上并发进行,提高了系统资源利用率,尤其适用于高并发、低延迟的网络应用。 ...
- **性能优化**:针对特定场景,可以对Socket编程进行优化,如使用NIO(非阻塞I/O)提高性能。 综上所述,这份实验报告不仅涵盖了Socket编程的基础知识,还提供了具体的Java代码示例,对于学习网络编程具有一定的...
Java的NIO(New IO)提供了一种非阻塞的I/O模型,可以提高多并发连接的效率。此外,TCP的Keep-Alive和 Nagle算法也可以根据实际情况调整,以优化网络性能。 总结,Java Socket结合SSL/TLS等安全技术,可以构建安全...
NIO(New IO)提供了一种更高效、非阻塞的I/O模型。 8. **网络编程**:Java提供了Socket编程接口,可以用来创建客户端和服务器端的通信应用。 9. **反射机制**:反射是Java的一个强大特性,允许程序在运行时动态地...
8. **IO与NIO**: Java IO提供基于流的输入输出操作,而NIO(非阻塞I/O)引入了通道和缓冲区,提升了高并发场景下的性能。 9. **集合框架**: 遍历HashMap、ArrayList、LinkedList、TreeSet等集合的实现原理,掌握...
4. 非阻塞Socket:Java NIO中的SocketChannel和ServerSocketChannel是非阻塞网络套接字,它们允许你在没有数据可读或可写时,不会挂起当前线程。 5. MBean和JMX工具:文章提到了使用MBean和Java管理扩展(JMX)工具...
2. **网络编程**:16章可能讲解了Java的Socket编程,包括TCP和UDP通信,以及ServerSocket和Socket类的使用,还有可能涉及到NIO(非阻塞I/O)和Netty框架的应用。 3. **数据持久化**:17章可能是关于数据库操作的...
5. **IO流与NIO**:讲解输入/输出流的使用,包括字节流、字符流、对象流,以及NIO(非阻塞I/O)的优势和用法,如通道、缓冲区和选择器。 6. **多线程编程**:涵盖线程的创建方式(继承Thread类与实现Runnable接口)...
- **非阻塞Socket**:介绍如何使用NIO来实现非阻塞式的Socket编程,提高程序效率。 - **多线程Socket编程**:讨论了如何在Java中利用多线程技术处理多个客户端的并发连接请求。 ##### 4. 高级主题 - **错误处理**...
3. **NIO(非阻塞I/O)**:Java NIO(New Input/Output)是Java 1.4引入的新特性,它提供了与传统IO不同的I/O操作方式,支持选择器(Selector)、通道(Channel)和缓冲区(Buffer)。NIO允许程序在数据准备好时进行...
4. **IO流与NIO**:这部分习题会测试你对输入输出流的理解,包括文件操作、对象序列化,以及新的NIO(非阻塞I/O)模型。 5. **多线程**:Java提供了丰富的多线程支持,习题可能包括同步机制(如synchronized关键字...
此外,NIO(非阻塞I/O)和AIO(异步I/O)也是现代服务端开发的热点,可能会涉及到。 **第五章:JVM优化** 理解Java虚拟机(JVM)的工作原理对性能调优至关重要。本章可能包含JVM内存模型、垃圾回收机制、类加载机制...
1. **Netty 框架**:Netty 是一个基于 NIO(非阻塞 I/O)的 Java 框架,提供了高度定制的事件循环(EventLoop)、通道(Channel)和管道(ChannelPipeline)机制,使得编写高性能、异步的网络应用变得简单。...
1. NIO基础:Netty基于Java NIO来实现非阻塞的网络通信,因此需要对Java NIO有一定的了解。 2. 事件处理:Netty采用事件驱动机制来处理各种网络事件,理解其事件处理模型是掌握Netty的关键。 3. ChannelPipeline:...