标签:figure puts cat nios 唤醒 直接 生产 关键点 int
一、问题BIO 和 NIO 作为 Server 端,当建立了 10 个连接时,分别产生多少个线程?
答案: 因为传统的 IO 也就是 BIO 是同步线程堵塞的,所以每个连接都要分配一个专用线程来处理请求,这样 10 个连接就会创建 10 个线程去处理。而 NIO 是一种同步非阻塞的 I/O 模型,它的核心技术是多路复用,可以使用一个链接上的不同通道来处理不同的请求,所以即使有 10 个连接,对于 NIO 来说,开启 1 个线程就够了。
public
class
DemoServer
extends
Thread
{
private
ServerSocket
serverSocket
;
public
int
getPort
()
{
return
serverSocket
.
getLocalPort
();
}
public
void
run
()
{
try
{
serverSocket
=
new
ServerSocket
(
0
);
while
(
true
)
{
Socket
socket
=
serverSocket
.
accept
();
RequestHandler
requestHandler
=
new
RequestHandler
(
socket
);
requestHandler
.
start
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
serverSocket
!=
null
)
{
try
{
serverSocket
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
public
static
void
main
(
String
[]
args
)
throws
IOException
{
DemoServer
server
=
new
DemoServer
();
server
.
start
();
try
(
Socket
client
=
new
Socket
(
InetAddress
.
getLocalHost
(),
server
.
getPort
()))
{
BufferedReader
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
client
.
getInputStream
()));
bufferedReader
.
lines
().
forEach
(
s
->
System
.
out
.
println
(
s
));
}
}
}
// 简化实现,不做读取,直接发送字符串
class
RequestHandler
extends
Thread
{
private
Socket
socket
;
RequestHandler
(
Socket
socket
)
{
this
.
socket
=
socket
;
}
@Override
public
void
run
()
{
try
(
PrintWriter
out
=
new
PrintWriter
(
socket
.
getOutputStream
());)
{
out
.
println
(
"Hello world!"
);
out
.
flush
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
(图片来源于杨晓峰)
public
class
NIOServer
extends
Thread
{
public
void
run
()
{
try
(
Selector
selector
=
Selector
.
open
();
ServerSocketChannel
serverSocket
=
ServerSocketChannel
.
open
();)
{
// 创建 Selector 和 Channel
serverSocket
.
bind
(
new
InetSocketAddress
(
InetAddress
.
getLocalHost
(),
8888
));
serverSocket
.
configureBlocking
(
false
);
// 注册到 Selector,并说明关注点
serverSocket
.
register
(
selector
,
SelectionKey
.
OP_ACCEPT
);
while
(
true
)
{
selector
.
select
();
// 阻塞等待就绪的 Channel,这是关键点之一
Set
<
SelectionKey
>
selectedKeys
=
selector
.
selectedKeys
();
Iterator
<
SelectionKey
>
iter
=
selectedKeys
.
iterator
();
while
(
iter
.
hasNext
())
{
SelectionKey
key
=
iter
.
next
();
// 生产系统中一般会额外进行就绪状态检查
sayHelloWorld
((
ServerSocketChannel
)
key
.
channel
());
iter
.
remove
();
}
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
private
void
sayHelloWorld
(
ServerSocketChannel
server
)
throws
IOException
{
try
(
SocketChannel
client
=
server
.
accept
();)
{
client
.
write
(
Charset
.
defaultCharset
().
encode
(
"Hello world!"
));
}
}
// 省略了与前面类似的 main
}
(图片来源于杨晓峰)
杨晓峰《Java核心36讲》
近期热门文章:
Java 最常见的 200+ 面试题
标签:figure puts cat nios 唤醒 直接 生产 关键点 int
原文地址:https://blog.51cto.com/13904087/2515745