- 浏览: 50320 次
- 性别:
文章分类
- 全部博客 (103)
- 一致性哈希算法 (1)
- 云计算 (2)
- Cassandra学习 (2)
- Java网络通信与笔记 (14)
- ZooKeeper学习 (1)
- HBase学习 (1)
- Sqoop学习 (1)
- Java网页开发之 (2)
- Java网络通信框架 (5)
- (memcached)分布式内存对象缓存系统 (1)
- Redis学习 (5)
- Shell学习 (14)
- Linux学习 (10)
- MySQL优化 (17)
- C++ (7)
- HTML5 (5)
- Android学习 (5)
- 网络 (2)
- Node.js (1)
- D3.js (1)
- R语言学习 (3)
- Spark (1)
- CAN协议 (2)
- 解决方案 (0)
最新评论
Java通信的几种IO设计
[size=large]阻塞IO
同步阻塞最常用的一种用法,使用也是最简单的,但是 I/O 性能一般很差,CPU 大部分在空闲状态。下面是一个简单的基于TCP的同步阻塞的Socket服务端例子:
@Test
public void testBlockIoSocket() throws Exception
{
ServerSocket serverSocket = new ServerSocket(10002);
Socket socket = null;
try
{
while (true)
{
socket = serverSocket.accept();
System.out.println("socket连接:" + socket.getRemoteSocketAddress().toString());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true)
{
String readLine = in.readLine();
System.out.println("收到消息" + readLine);
if("end".equals(readLine))
{
break;
}
//客户端断开连接
socket.sendUrgentData(0xFF);
}
}
}
catch (SocketException se)
{
System.out.println("客户端断开连接");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
System.out.println("socket关闭:" + socket.getRemoteSocketAddress().toString());
socket.close();
}
}
设计分析:
由于服务器端是单线程的,在第一个连接的客户端阻塞了线程后,第二个客户端必须等待第一个断开后才能连接。
所有的客户端连接在请求服务端时都会阻塞住,等待前面的完成。即使是使用短连接,数据在写入 OutputStream 或者从 InputStream 读取时都有可能会阻塞。这在大规模的访问量或者系统对性能有要求的时候是不能接受的。
阻塞IO + 每个请求创建线程/线程池
通常解决这个问题的方法是使用多线程技术,一个客户端一个处理线程,出现阻塞时只是一个线程阻塞而不会影响其它线程工作;为了减少系统线程的开销,采用线程池的办法来减少线程创建和回收的成本。模式如下图:
每当来一个客户端的连接的时候,我们服务器就new 一个线程来处理它。在服务器的主程序是不阻塞的,阻塞的只是这个线程。这样也是我目前最常用的模式。
在单个线程处理中,我人为的使单个线程read后阻塞5秒,就像前面说的,出现阻塞也只是在单个线程中,没有影响到另一个客户端的处理。
这种阻塞IO的解决方案在大部分情况下是适用的,在出现NIO之前是最通常的解决方案,Tomcat里阻塞IO的实现就是这种方式。但是如果是大量的长连接请求呢?不可能创建几百万个线程保持连接。再退一步,就算线程数不是问题,如果这些线程都需要访问服务端的某些竞争资源,势必需要进行同步操作,这本身就是得不偿失的。
非阻塞IO + IO multiplexing Java从1.4开始提供了NIO工具包,这是一种不同于传统流IO的新的IO方式,使得Java开始对非阻塞IO支持;NIO并不等同于非阻塞IO,只要设置Blocking属性就可以控制阻塞非阻塞。至于NIO的工作方式特点原理这里一概不说,以后会写。模式如下图:
public class NioNonBlockingSelectorTest
{
Selector selector;
private ByteBuffer receivebuffer = ByteBuffer.allocate(1024);
@Test
public void testNioNonBlockingSelector()
throws Exception
{
selector = Selector.open();
SocketAddress address = new InetSocketAddress(10002);
ServerSocketChannel channel = ServerSocketChannel.open();
channel.socket().bind(address);
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_ACCEPT);
while(true)
{
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
iterator.remove();
handleKey(selectionKey);
}
}
}
private void handleKey(SelectionKey selectionKey) throws IOException
{
ServerSocketChannel server = null;
SocketChannel client = null;
if(selectionKey.isAcceptable())
{
server = (ServerSocketChannel)selectionKey.channel();
client = server.accept();
System.out.println("客户端: " + client.socket().getRemoteSocketAddress().toString());
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
if(selectionKey.isReadable())
{
client = (SocketChannel)selectionKey.channel();
receivebuffer.clear();
int count = client.read(receivebuffer);
if (count > 0) {
String receiveText = new String( receivebuffer.array(),0,count);
System.out.println("服务器端接受客户端数据--:" + receiveText);
client.register(selector, SelectionKey.OP_READ);
}
}
}
}
Java NIO提供的非阻塞IO并不是单纯的非阻塞IO模式,而是建立在Reactor模式上的IO复用模型;在IO multiplexing Model中,对于每一个socket,一般都设置成为non-blocking,但是整个用户进程其实是一直被阻塞的。只不过进程是被select这个函数阻塞,而不是被socket IO给阻塞,所以还是属于非阻塞的IO。
网络IO优化
对于网络IO有一些基本的处理规则如下:
1。减少交互的次数。比如增加缓存,合并请求。
2。减少传输数据大小。比如压缩后传输、约定合理的数据协议。
3。减少编码。比如提前将字符转化为字节再传输。
4。根据应用场景选择合适的交互方式,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞。
[/size]
[size=large]阻塞IO
同步阻塞最常用的一种用法,使用也是最简单的,但是 I/O 性能一般很差,CPU 大部分在空闲状态。下面是一个简单的基于TCP的同步阻塞的Socket服务端例子:
@Test
public void testBlockIoSocket() throws Exception
{
ServerSocket serverSocket = new ServerSocket(10002);
Socket socket = null;
try
{
while (true)
{
socket = serverSocket.accept();
System.out.println("socket连接:" + socket.getRemoteSocketAddress().toString());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true)
{
String readLine = in.readLine();
System.out.println("收到消息" + readLine);
if("end".equals(readLine))
{
break;
}
//客户端断开连接
socket.sendUrgentData(0xFF);
}
}
}
catch (SocketException se)
{
System.out.println("客户端断开连接");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
System.out.println("socket关闭:" + socket.getRemoteSocketAddress().toString());
socket.close();
}
}
设计分析:
由于服务器端是单线程的,在第一个连接的客户端阻塞了线程后,第二个客户端必须等待第一个断开后才能连接。
所有的客户端连接在请求服务端时都会阻塞住,等待前面的完成。即使是使用短连接,数据在写入 OutputStream 或者从 InputStream 读取时都有可能会阻塞。这在大规模的访问量或者系统对性能有要求的时候是不能接受的。
阻塞IO + 每个请求创建线程/线程池
通常解决这个问题的方法是使用多线程技术,一个客户端一个处理线程,出现阻塞时只是一个线程阻塞而不会影响其它线程工作;为了减少系统线程的开销,采用线程池的办法来减少线程创建和回收的成本。模式如下图:
每当来一个客户端的连接的时候,我们服务器就new 一个线程来处理它。在服务器的主程序是不阻塞的,阻塞的只是这个线程。这样也是我目前最常用的模式。
在单个线程处理中,我人为的使单个线程read后阻塞5秒,就像前面说的,出现阻塞也只是在单个线程中,没有影响到另一个客户端的处理。
这种阻塞IO的解决方案在大部分情况下是适用的,在出现NIO之前是最通常的解决方案,Tomcat里阻塞IO的实现就是这种方式。但是如果是大量的长连接请求呢?不可能创建几百万个线程保持连接。再退一步,就算线程数不是问题,如果这些线程都需要访问服务端的某些竞争资源,势必需要进行同步操作,这本身就是得不偿失的。
非阻塞IO + IO multiplexing Java从1.4开始提供了NIO工具包,这是一种不同于传统流IO的新的IO方式,使得Java开始对非阻塞IO支持;NIO并不等同于非阻塞IO,只要设置Blocking属性就可以控制阻塞非阻塞。至于NIO的工作方式特点原理这里一概不说,以后会写。模式如下图:
public class NioNonBlockingSelectorTest
{
Selector selector;
private ByteBuffer receivebuffer = ByteBuffer.allocate(1024);
@Test
public void testNioNonBlockingSelector()
throws Exception
{
selector = Selector.open();
SocketAddress address = new InetSocketAddress(10002);
ServerSocketChannel channel = ServerSocketChannel.open();
channel.socket().bind(address);
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_ACCEPT);
while(true)
{
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
iterator.remove();
handleKey(selectionKey);
}
}
}
private void handleKey(SelectionKey selectionKey) throws IOException
{
ServerSocketChannel server = null;
SocketChannel client = null;
if(selectionKey.isAcceptable())
{
server = (ServerSocketChannel)selectionKey.channel();
client = server.accept();
System.out.println("客户端: " + client.socket().getRemoteSocketAddress().toString());
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
if(selectionKey.isReadable())
{
client = (SocketChannel)selectionKey.channel();
receivebuffer.clear();
int count = client.read(receivebuffer);
if (count > 0) {
String receiveText = new String( receivebuffer.array(),0,count);
System.out.println("服务器端接受客户端数据--:" + receiveText);
client.register(selector, SelectionKey.OP_READ);
}
}
}
}
Java NIO提供的非阻塞IO并不是单纯的非阻塞IO模式,而是建立在Reactor模式上的IO复用模型;在IO multiplexing Model中,对于每一个socket,一般都设置成为non-blocking,但是整个用户进程其实是一直被阻塞的。只不过进程是被select这个函数阻塞,而不是被socket IO给阻塞,所以还是属于非阻塞的IO。
网络IO优化
对于网络IO有一些基本的处理规则如下:
1。减少交互的次数。比如增加缓存,合并请求。
2。减少传输数据大小。比如压缩后传输、约定合理的数据协议。
3。减少编码。比如提前将字符转化为字节再传输。
4。根据应用场景选择合适的交互方式,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞。
[/size]
发表评论
-
Java之Concurrent(并发)包
2015-09-25 16:31 313因为实在是太多了,太长了,一时间无法自习整理和消化,先 ... -
Java集合框架
2015-09-25 16:31 389集合框架有很多的 ... -
final, finally, finalize的区别
2015-09-19 11:39 3861.final final修饰类,说明 ... -
四种会话跟踪技术
2015-09-19 11:36 772会话跟踪是一种灵活、轻便的机制,它使Web上的状态编程变为可能 ... -
java中volatile关键字的含义
2015-09-19 10:59 376在java线程并发处理中, ... -
java笔记--关于线程同步(5种同步方式)
2015-09-19 10:21 413[size=medium]为何要使用同步? java ... -
RPC
2015-07-30 11:04 386RPC 功能目标 RPC 的 ... -
Java NIO原理文分析及代码实现
2015-07-22 10:43 426Java NIO原理图文分析及代码实现 前言: 最近在分 ... -
NIO学习(一)
2015-07-22 10:43 325[size=medium]NIO学习 一.NIO中的几个基础 ... -
Java IO浅谈
2015-07-21 13:12 304Java IO浅谈 [size=large] ... -
线程池(二)
2015-07-21 12:29 360Java ... -
线程池(一)
2015-07-21 12:11 362线程池 在上一篇博客中,我们有提及阻塞IO的为每个连接请求 ... -
阻塞与非阻塞-----同步与异步
2015-07-21 11:31 477阻塞(blocking)与非阻塞(non-blocking)I ...
相关推荐
"04IO设计模式.zip"这个压缩包包含了一个名为"IO设计模式了解.flv"的视频文件,很可能是对I/O设计模式的讲解或演示。虽然没有具体的标签信息,但我们可以根据I/O设计模式的主题来展开讨论。 首先,I/O设计模式是...
在.NET开发环境中,设计模式是解决常见编程问题的模板,它们是经过时间验证的最佳实践,可以帮助我们编写可扩展、可维护的代码。本篇文章将深入探讨以下几种.NET设计模式:抽象工厂模式、单例模式、工厂方法模式、...
Java作为一门流行的编程语言,其标准库(JDK)中巧妙地融入了多种设计模式的应用。本文将详细介绍在JDK中体现的23种经典设计模式,并通过具体的代码示例进行说明。 #### 二、设计模式分类 设计模式可以大致分为三类...
Java 设计模式最佳实践是软件开发中的重要主题,它涵盖了多种模式,这些模式已被广泛接受并应用于实际项目中,以解决常见的编程问题和提升代码的可读性、可维护性和可扩展性。在这个主题中,我们将深入探讨一些关键...
STM32微控制器的GPIO...总结来说,STM32的GPIO口配置多种多样,针对不同的应用场景,可以选择最合适的模式,以确保设备的正常运行。对于新手而言,理解这些模式的区别和特点对于掌握STM32微控制器的使用至关重要。
Java的23种设计模式是软件工程中非常重要的概念,它们是解决常见编程问题的成熟解决方案,被广泛应用于各种复杂的软件开发中。设计模式不是具体的代码或库,而是一种通用的、可重用的设计方案,它描述了在特定上下文...
在Java中,设计模式的运用非常广泛,一些JDK类库中就融入了多种设计模式,以增强代码的灵活性和可维护性。 单例模式(Singleton pattern)是创建型模式的一种,它确保一个类只有一个实例,并提供一个全局访问点。在...
设计模式则是软件开发中的最佳实践,它们是解决常见问题的模板,可以在不同场景下重复使用,以提高代码的可读性、可维护性和灵活性。 在Java EE开发中,设计模式扮演着至关重要的角色。以下是一些在Java EE开发中...
Java JDK中广泛使用了各种设计模式,例如单例模式在许多系统类中,如`java.lang.Runtime`,工厂模式在集合框架中,装饰器模式在`java.io`包中,适配器模式在I/O流中等等。 面向对象设计原则包括开闭原则(对扩展...
《JAVA设计模式之禅》是一本深入浅出地讲解JAVA设计模式的书籍,结合了中国的古典故事,使得抽象的设计模式概念变得生动形象,易于理解。设计模式是软件工程中的重要概念,它们是针对常见问题的解决方案,经过时间和...
Java企业设计模式是软件开发中的一种重要思想,它在Java应用程序开发中扮演着核心角色,尤其是在大型企业级项目中。设计模式是对在特定上下文中反复出现的问题及其解决方案的描述,这些解决方案已被证明在许多情况下...
在IT领域,设计模式是软件开发中的重要概念,它代表了在特定上下文中解决常见问题的最佳实践。Java作为广泛使用的编程语言,与设计模式的结合是编写可维护、可扩展和高效代码的关键。本篇文章将深入探讨Java与设计...
单片机通过编程可以配置这些IO口的模式,实现灵活的数据传输。同时,CPLD则可以处理高速、高密度的IO操作,比如并行数据转换、同步信号生成等。 CPLD的编程通常使用硬件描述语言(HDL),如VHDL或Verilog,通过逻辑...
根据具体的应用需求,IO口可以配置成多种不同的工作模式,包括但不限于普通输入、模拟输入、开漏输出、推挽输出等。 #### 二、IO口的工作模式详解 1. **普通输入** - **定义**:普通输入模式是最简单的输入模式...
设计模式是软件工程中的一种最佳实践,它是在特定情境下为了解决常见问题而形成的一套可重用的解决方案。在Java中,设计模式的应用能够提高代码的可读性、可维护性和可扩展性,是每个Java开发者必备的技能之一。本...
此外,RapidIO还支持无连接的通信方式,这种模式下,数据包的传输不依赖于之前的连接状态,适用于一些延迟敏感或数据量小的场合。 RapidIO技术的一个显著特点是其高效的流量控制机制。流量控制是确保数据传输不会...
在本文中,我们将对 10 道 Java 面试必备的设计模式面试题进行详细的解析,涵盖了单例模式、观察者模式、工厂模式、装饰器模式等多种设计模式。 1. JDK 中常用的设计模式 在 JDK 中,有多种常用的设计模式,例如...
Python提供了多种并发模型,如线程(threading模块)、进程(multiprocessing模块)以及异步IO(asyncio模块)。理解这些模型的工作原理以及如何在不同场景下选择合适的模型,能够优化程序的执行效率,提高系统资源...
除了Observer模式,Java类库还体现了其他多种设计模式。如Singleton模式,用于确保一个类只有一个实例,并提供全局访问点,如`java.lang.Runtime`类;Factory模式,用于创建对象的接口,如`java.sql.DriverManager`...
分布式IO系统是相对于集中式IO的一种设计模式,它允许IO模块分布在系统的不同位置,更靠近现场设备,从而降低布线成本,提高系统响应速度和可靠性。 罗克韦尔的分布式IO系统主要基于ControlLogix、CompactLogix或...