Java Web 深入分析(4) Java IO 深入分析
I/O问题可以说是现在海量数据时代下 ,I/O大部分web系统的瓶颈。我们要了解的java I/O(后面简称为(IO))
- IO类库的基本结构
- 磁盘IO的工作机制
- 网络IO的工作机制
- NIO的工作方式
- 同步异步、阻塞非阻塞的区别
- IO优化技巧
IO类库的基本结构
字节流InputStream
提供public abstract int read() throws IOException;
public int read(byte b[]) throws IOException
public int read(byte b[], int off, int len) throws IOException3个读取方法
字节流OutputStream
提供public abstract void write(int b) throws IOException
public void write(byte b[]) throws IOException
public void write(byte b[], int off, int len) throws IOException
public void flush() throws IOException 4个输出方法
总结:不细说如何使用,关键流 可以组合使用,然后要么写到磁盘,要么写到网络,其实写网络也是写文件,不过会有特殊处理,就是让操作系统通过 传输到其他地方。
字符流Writer
Writer提供public void write(String str, int off, int len) throws IOException
public Writer append(CharSequence csq) throws IOException
abstract public void flush() throws IOException 等方法
字符流Reader
Writer提供public int read(java.nio.CharBuffer target) throws IOException
abstract public int read(char cbuf[], int off, int len) throws IOException;
public long skip(long n) throws IOException 等方法
总结:不管是网络还是磁盘传输,最小的存储单元都是字节,而不是字符,转换存在着耗时和烦人的编码问题,所以Java提供了字符流,注意无论是字符还是字节流都有共同的方法那就是close()方法
字节和字符的转换:InputStreamReader和OutPutStreamWriter
上图就是字符解码的过程,举例来说:假设你用FileReader去读取文件,FileReader继承了InputStreamReader,实际上就是读取文件流,然后通过StreamDecoder解码成了char,然后大多数情况下是默认的系统字符集Charset,同理字符编码类似,如下图
磁盘IO的工作机制
标准文件访问方式:读取先读高速缓存,若无则取磁盘;写入就是先将用户地址空间数据搬移到系统高速缓存块,然后有操作系统决定何时写入物理磁盘。
直接IO的方式:应用程序直接从磁盘读取数据,经典的就是数据库管理系统,数据库系统明确知道热点数据,会提前加载到内存中。通常是直接io和异步io结合使用。
同步访问件方式:顾名思义就是数据读写都是同步操作,与标准文件访问方式不同,只有数据真正写入到磁盘才会返回给应用程序写入成功标志。通常用于数据安全性较高的场景,也采用硬件定制的方式。
异步访问文件方式:访问数据的线程发出请求后并不是阻塞等待而是继续下面的操作。提高的是应用程序效率而不是访问文件的效率。
内存映射访问方式:查询系统将一块内存区域与磁盘文件关联起来,当需要访问磁盘数据改为访问高速缓存数据,减少从高速缓存加载硬盘数据,又去复制到程序内存的操作。
网络IO的工作方式
下面演示C/S socket udp nio
- 服务端
package ocr.test;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(10086);//创建serversocket 并绑定端口 10086 1024-65535之间,因为0-1024间有许多操作系统重要端口
System.out.println(">>>>>>>>>>>服务器已经启动!");
Socket socket =server.accept();//阻塞进程等待着 客户端连接
InputStream is =socket.getInputStream();//得到输入流
InputStreamReader isr = new InputStreamReader(is); //字符字节转换流
BufferedReader br = new BufferedReader(isr);//得到缓冲流
String msg = "";
while((msg=br.readLine() )!= null){
System.out.println("服务器:已经接收到客户端信息="+msg);
}
OutputStream os=socket.getOutputStream();//
PrintWriter pw = new PrintWriter(os);//
pw.write("欢迎客户端"+socket.getLocalAddress());
pw.flush();//刷新数据流
br.close();
isr.close();
is.close();
socket.close();
server.close();
os.close();
pw.close();
}
}
- 客户端
package ocr.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class client {
public static void main(String[] args) throws IOException, Exception {
Socket socket = new Socket("localhost", 10086);
System.out.println(">>>>>>>>>>>客户端已经启动!");
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
osw.write("用户User密码123");
osw.flush();
socket.shutdownOutput();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String msg ="";
while((msg =br.readLine())!=null){
System.out.println("客户端:接收到服务器信息="+msg);
}
br.close();
isr.close();
is.close();
osw.close();
os.close();
socket.close();
}
}
- 测试效果:
- UDP通信
服务端:
package ocr.test;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(10086);
byte[] msg = new byte[1024];
DatagramPacket pocket = new DatagramPacket(msg, msg.length);
socket.receive(pocket);
String msgs = new String(msg, 0, msg.length);
System.out.println("服务器:已经接收到客户端信息="+msgs);
InetAddress address = pocket.getAddress();
int port = pocket.getPort();
byte[] sendmsg = ("欢迎您"+port).getBytes();
DatagramPacket pocket2 = new DatagramPacket(sendmsg, sendmsg.length, address, port);
socket.send(pocket2);
socket.close();
}
}
客户端:
package ocr.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class client {
public static void main(String[] args) throws IOException, Exception {
//客户端
//1、定义服务器的地址、端口号、数据
InetAddress address =InetAddress.getByName("localhost");
int port =10086;
byte[] data ="用户名:admin;密码:123".getBytes();
//2、创建数据报,包含发送的数据信息
DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
//3、创建DatagramSocket对象
DatagramSocket socket =new DatagramSocket();
//4、向服务器发送数据
socket.send(packet);
//接受服务器端响应数据
//======================================
//1、创建数据报,用于接受服务器端响应数据
byte[] data2 = new byte[1024];
DatagramPacket packet2 = new DatagramPacket(data2,data2.length);
//2、接受服务器响应的数据
socket.receive(packet2);
String raply = new String(data2,0,packet2.getLength());
System.out.println("我是客户端,服务器说:"+raply);
//4、关闭资源
socket.close();
}
}
- java NIO:前面讲到的是BIO,无论是磁盘还是网络,都存在一个致命缺点就是:阻塞。当一个线程阻塞是,其他线程失去了CPU的使用权。于是我们需要nio这种通信方式。
客户端:给出一个方法!
public static void client(){
ByteBuffer buffer = ByteBuffer.allocate(1024);
SocketChannel socketChannel = null;
try
{
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost",8080));
if(socketChannel.finishConnect())
{
int i=0;
while(true)
{
TimeUnit.SECONDS.sleep(1);
String info = "I'm "+i+++"-th information from client";
buffer.clear();
buffer.put(info.getBytes());
buffer.flip();
while(buffer.hasRemaining()){
System.out.println(buffer);
socketChannel.write(buffer);
}
}
}
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
finally{
try{
if(socketChannel!=null){
socketChannel.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
服务端:
package ocr.test;
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;
public class ServerConnect
{
private static final int BUF_SIZE=1024;
private static final int PORT = 8080;
private static final int TIMEOUT = 3000;
public static void main(String[] args)
{
selector();
}
public static void handleAccept(SelectionKey key) throws IOException{
ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel();
SocketChannel sc = ssChannel.accept();
sc.configureBlocking(false);
sc.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocateDirect(BUF_SIZE));
}
public static void handleRead(SelectionKey key) throws IOException{
SocketChannel sc = (SocketChannel)key.channel();
ByteBuffer buf = (ByteBuffer)key.attachment();
long bytesRead = sc.read(buf);
while(bytesRead>0){
buf.flip();
while(buf.hasRemaining()){
System.out.print((char)buf.get());
}
System.out.println();
buf.clear();
bytesRead = sc.read(buf);
}
if(bytesRead == -1){
sc.close();
}
}
public static void handleWrite(SelectionKey key) throws IOException{
ByteBuffer buf = (ByteBuffer)key.attachment();
buf.flip();
SocketChannel sc = (SocketChannel) key.channel();
while(buf.hasRemaining()){
sc.write(buf);
}
buf.compact();
}
public static void selector() {
Selector selector = null;
ServerSocketChannel ssc = null;
try{
selector = Selector.open();
ssc= ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(PORT));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
while(true){
if(selector.select(TIMEOUT) == 0){
System.out.println("==");
continue;
}
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while(iter.hasNext()){
SelectionKey key = iter.next();
if(key.isAcceptable()){
handleAccept(key);
}
if(key.isReadable()){
handleRead(key);
}
if(key.isWritable() && key.isValid()){
handleWrite(key);
}
if(key.isConnectable()){
System.out.println("isConnectable = true");
}
iter.remove();
}
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(selector!=null){
selector.close();
}
if(ssc!=null){
ssc.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
nio 更多参考:
[http://www.importnew.com/19816.html]{http://www.importnew.com/19816.html}
Java Web 深入分析(4) Java IO 深入分析的更多相关文章
- Java web项目引用java项目,类型找不到
Java web项目引用java项目,类型找不到 错误信息: java.lang.ClassNotFoundException: org.codehaus.jackson.map.ObjectMapp ...
- Java Web项目与Java项目的区别
一.以下是我对Java Web项目和Java项目这两者的理解以及区别: 1.Java Web项目是基于Java EE类的:而Java项目是基于Java应用程序的. 2.Java Web项目是网页的编码 ...
- Java Web系列:Java Web 项目基础
1.Java Web 模块结构 JSP文件和AXPX文件类似,路径和URL一一对应,都会被动态编译为单独class.Java Web和ASP.NET的核心是分别是Servlet和IHttpHandle ...
- java web项目和java项目的区别(看清IDE本质)
想必大家在使用MyEclipse时对这两个概念不去深究.只知道是Java EE类的基本都是Web项目,而Java应用程序就是Java项目.而且很多人都愿意使用MyEclipse作为开发工具,且不说大家 ...
- java web mysql.jar java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 折腾了一上午,找到了这错误的原因.哎……悲剧! 确认包已经被导入web工程目录. 原来是 ...
- Java web项目中java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
原来是tomcat找不到MYSQL JAR包的问题.后来又把mysql-connector-java-5.1.7-bin.jar导入到tomcat的lib目录下面就ok了,嘿…… 在java项目中,只 ...
- java web 学习笔记 - Java Bean
1. Java Bean 是一个简单的 java 类,一般放在WEB-INF下的 classes目录下(如果没有则需要手工新建) 一个简单的Bean包括属性,getter ,setter方法,如果没有 ...
- java web项目,java类中获得WEB-INF路径
private static String getWebInfPath() { URL url = 当前类.class.getProtectionDomain().getCodeSource().ge ...
- JAVA Coder 的《深入分析Java Web 技术内幕》读书笔记
本文基于<深入分析Java Web 技术内幕> <深入分析Java Web 技术内幕>,作者是 许令波,电子工业出版社.本文只是记录书本当中的精彩部分,作个人回顾和技术分享,请 ...
- 五分钟学Java:如何才能学好Java Web里这么多的技术
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 系列文章介绍 本文是<五分钟学Java>系列文章的一篇 本系列文章主要围绕Java程序员必须掌握的核心技能,结合我个人三年 ...
随机推荐
- 【Oracle/Java】向三张表各插入百万数据,共用时18分3秒,平均每张表6分钟
三张表DDL如下: CREATE TABLE tb01 ( "ID" ,) not null primary key, "NAME" NVARCHAR2() n ...
- 寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现。本文记录HAProxy服务热加载后某微服务50%概率失效的问题。设计3组对比实验,验证了陈旧配置的HAProxy在Reload时没有退出进而导致微服务丢失,并给出了解决方案. Keywords:HAProxy热加
寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现.本文记录HAPro ...
- iOS8.0如何使用Touch ID来做验证
对于Objective-C而言,只要几行代码即可搞定. 比如: #import <LocalAuthentication/LocalAuthentication.h> - (void)vi ...
- warning: deleting 'void *' is undefined 错误
如果我们new出来的指针是一个基本类型,没什么关系,内存还是会被释放的,但是如果是一个类对象指针,在处理过程中转成了void*,那就有问题了,析构函数将不会被调用. 故new的指针类型要和delete ...
- 利用python批量修改word文件名的方法示例
利用python批量修改word文件名的方法示例 最近不小心把硬盘给格式化了,由于当时的文件没有备份,所以一下所有的文件都没有了,于是只能采取补救措施,用文件恢复软件恢复了一部分的数据出来,但是恢复完 ...
- LNMP一键环境安装多PHP版本共存的方法
多PHP版本只支持LNMP模式,LNMPA.LAMP模式下不支持!要使用多PHP先安装多PHP版本,在lnmp1.4源码(lnmp1.3的不行哦)目录下运行:./install.sh mphp 按提示 ...
- python reduce和偏函数partial
functools模块 reduce方法: reduce方法 reduce方法,顾名思义就是减少 可迭代对象不能为空,初始值没提供就在可迭代对象中去一个元素 from functools import ...
- 【Leetcode_easy】665. Non-decreasing Array
problem 665. Non-decreasing Array 题意:是否能够将数组转换为非减数组. solution: 难点在于理解如何对需要修改的元素进行赋值: class Solution ...
- 【Leetcode_easy】661. Image Smoother
problem 661. Image Smoother 题意:其实类似于图像处理的均值滤波. solution: 妙处在于使用了一个dirs变量来计算邻域数值,看起来更简洁! class Soluti ...
- Docker Swarm 集群(十七)
目录 一.Docker Swarm 概念 1.集群 2.Docker Swarm 3.重要概念 swarm node service 二.创建 Swarm 集群 1.环境准备 2.创建 swarm 3 ...