Skip to content

Commit

Permalink
补充:IO、反射、动态代理 相关知识点
Browse files Browse the repository at this point in the history
  • Loading branch information
hollis.zhl committed Jun 1, 2019
1 parent baa1ff4 commit 84e352a
Show file tree
Hide file tree
Showing 15 changed files with 627 additions and 9 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,29 +145,29 @@ apache集合处理工具类的使用、

#### IO

字符流字节流输入流输出流
[字符流字节流](/basics/java-basic/byte-stream-vs-character-stream.md)、[输入流输出流](/basics/java-basic/input-stream-vs-output-stream.md)

同步异步阻塞非阻塞Linux 5种IO模型
[同步异步](/basics/java-basic/synchronized-vs-asynchronization.md)、[阻塞非阻塞](/basics/java-basic/block-vs-non-blocking.md)、[Linux 5种IO模型](/basics/java-basic/linux-io.md)

BIONIO和AIO的区别三种IO的用法与原理netty
[BIONIO和AIO的区别三种IO的用法与原理](/basics/java-basic/bio-vs-nio-vs-aio.md)netty

#### Java反射与javassist

反射与工厂模式反射有什么作用
[反射](/basics/java-basic/reflection.md)与工厂模式、 [反射有什么作用](/basics/java-basic/usage-of-reflection.md)

Class类
[Class类](/basics/java-basic/Class.md)

`java.lang.reflect.*`

#### 动态代理

静态代理动态代理
[静态代理](/basics/java-basic/static-proxy.md)、[动态代理](/basics/java-basic/dynamic-proxy.md)

动态代理和反射的关系
[动态代理和反射的关系](/basics/java-basic/dynamic-proxy-vs-reflection.md)

动态代理的几种实现方式
[动态代理的几种实现方式](/basics/java-basic/dynamic-proxy-implementation.md)

AOP
[AOP](/basics/java-basic/aop-vs-proxy.md)

#### 序列化

Expand Down
5 changes: 5 additions & 0 deletions basics/java-basic/Class.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息

Java.lang.Class是一个比较特殊的类它用于封装被装入到JVM中的类包括类和接口的信息当一个类或接口被装入的JVM时便会产生一个与之关联的java.lang.Class对象可以通过这个Class对象对被装入类的详细信息进行访问

虚拟机为每种类型管理一个独一无二的Class对象也就是说每个类都有一个Class对象运行程序时Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载如果没有加载JVM就会根据类名查找.class文件并将其Class对象载入
7 changes: 7 additions & 0 deletions basics/java-basic/aop-vs-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Spring AOP中的动态代理主要有两种方式JDK动态代理和CGLIB动态代理

JDK动态代理通过反射来接收被代理的类并且要求被代理的类必须实现一个接口JDK动态代理的核心是InvocationHandler接口和Proxy类

如果目标类没有实现接口那么Spring AOP会选择使用CGLIB来动态代理目标类

CGLIBCode Generation Library),是一个代码生成的类库可以在运行时动态的生成某个类的子类注意CGLIB是通过继承的方式做的动态代理因此如果某个类被标记为final那么它是无法使用CGLIB做动态代理的
265 changes: 265 additions & 0 deletions basics/java-basic/bio-vs-nio-vs-aio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
### IO
什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口它对于任何计算机系统都非常关键因而所有 I/O 的主体实际上是内置在操作系统中的单独的程序一般是让系统为它们完成大部分的工作

Java 编程中直到最近一直使用 的方式完成 I/O所有 I/O 都被视为单个的字节的移动通过一个称为 Stream 的对象一次移动一个字节 I/O 用于与外部世界接触它也在内部使用用于将对象转换为字节然后再转换回对象

### BIO

Java BIO即Block I/O同步并阻塞的IO

BIO就是传统的java.io包下面的代码实现

### NIO

什么是NIO? NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式原来的 I/O 以流的方式处理数据 NIO 以块的方式处理数据

面向流 I/O 系统一次一个字节地处理数据一个输入流产生一个字节的数据一个输出流消费一个字节的数据为流式数据创建过滤器非常容易链接几个过滤器以便每个过滤器只负责单个复杂处理机制的一部分这样也是相对简单的不利的一面是面向流的 I/O 通常相当慢

一个 面向块 I/O 系统以块的形式处理数据每一个操作都在一步中产生或者消费一个数据块按块处理数据比按(流式的)字节处理数据要快得多但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性

### AIO

Java AIO即Async非阻塞是异步非阻塞的IO

### 区别及联系

BIOBlocking I/O):同步阻塞I/O模式数据的读取写入必须阻塞在一个线程内等待其完成这里假设一个烧开水的场景有一排水壶在烧开水BIO的工作模式就是叫一个线程停留在一个水壶那直到这个水壶烧开才去处理下一个水壶但是实际上线程在等待水壶烧开的时间段什么都没有做

NIONew I/O):同时支持阻塞与非阻塞模式但这里我们以其同步非阻塞I/O模式来说明那么什么叫做同步非阻塞如果还拿烧开水来说NIO的做法是叫一个线程不断的轮询每个水壶的状态看看是否有水壶的状态发生了改变从而进行下一步的操作

AIOAsynchronous I/O):异步非阻塞I/O模型异步非阻塞与同步非阻塞的区别在哪里异步非阻塞无需一个线程去轮询所有IO操作的状态改变在相应的状态改变后系统会通知对应的线程来处理对应到烧开水中就是为每个水壶上面装了一个开关水烧开之后水壶会自动通知我水烧开了

### 各自适用场景

BIO方式适用于连接数目比较小且固定的架构这种方式对服务器资源要求比较高并发局限于应用中JDK1.4以前的唯一选择但程序直观简单易理解

NIO方式适用于连接数目多且连接比较短轻操作的架构比如聊天服务器并发局限于应用中编程比较复杂JDK1.4开始支持

AIO方式适用于连接数目多且连接比较长重操作的架构比如相册服务器充分调用OS参与并发操作编程比较复杂JDK7开始支持

### 使用方式

#### 使用BIO实现文件的读取和写入


```

//Initializes The Object
User1 user = new User1();
user.setName("hollis");
user.setAge(23);
System.out.println(user);

//Write Obj to File
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(oos);
}

//Read Obj from File
File file = new File("tempFile");
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(file));
User1 newUser = (User1) ois.readObject();
System.out.println(newUser);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(ois);
try {
FileUtils.forceDelete(file);
} catch (IOException e) {
e.printStackTrace();
}
}

//Initializes The Object
User1 user = new User1();
user.setName("hollis");
user.setAge(23);
System.out.println(user);

//Write Obj to File
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(oos);
}

//Read Obj from File
File file = new File("tempFile");
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(file));
User1 newUser = (User1) ois.readObject();
System.out.println(newUser);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(ois);
try {
FileUtils.forceDelete(file);
} catch (IOException e) {
e.printStackTrace();
}
}

```

#### 使用NIO实现文件的读取和写入

```

static void readNIO() {
String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";
FileInputStream fin = null;
try {
fin = new FileInputStream(new File(pathname));
FileChannel channel = fin.getChannel();

int capacity = 100;// 字节
ByteBuffer bf = ByteBuffer.allocate(capacity);
System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()
+ "位置是:" + bf.position());
int length = -1;

while ((length = channel.read(bf)) != -1) {

/*
* 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储
*/
bf.clear();
byte[] bytes = bf.array();
System.out.write(bytes, 0, length);
System.out.println();

System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()
+ "位置是:" + bf.position());

}

channel.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fin != null) {
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

static void writeNIO() {
String filename = "out.txt";
FileOutputStream fos = null;
try {

fos = new FileOutputStream(new File(filename));
FileChannel channel = fos.getChannel();
ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");
// 字节缓冲的容量和limit会随着数据长度变化,不是固定不变的
System.out.println("初始化容量和limit:" + src.capacity() + ","
+ src.limit());
int length = 0;

while ((length = channel.write(src)) != 0) {
/*
* 注意,这里不需要clear,将缓冲中的数据写入到通道中后 第二次接着上一次的顺序往下读
*/
System.out.println("写入长度:" + length);
}

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

```

#### 使用AIO实现文件的读取和写入

```
public class ReadFromFile {
public static void main(String[] args) throws Exception {
Path file = Paths.get("/usr/a.txt");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);

ByteBuffer buffer = ByteBuffer.allocate(100_000);
Future<Integer> result = channel.read(buffer, 0);

while (!result.isDone()) {
ProfitCalculator.calculateTax();
}
Integer bytesRead = result.get();
System.out.println("Bytes read [" + bytesRead + "]");
}
}
class ProfitCalculator {
public ProfitCalculator() {
}
public static void calculateTax() {
}
}

public class WriteToFile {

public static void main(String[] args) throws Exception {
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
Paths.get("/asynchronous.txt"), StandardOpenOption.READ,
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {

@Override
public void completed(Integer result, Object attachment) {
System.out.println("Attachment: " + attachment + " " + result
+ " bytes written");
System.out.println("CompletionHandler Thread ID: "
+ Thread.currentThread().getId());
}

@Override
public void failed(Throwable e, Object attachment) {
System.err.println("Attachment: " + attachment + " failed with:");
e.printStackTrace();
}
};

System.out.println("Main Thread ID: " + Thread.currentThread().getId());
fileChannel.write(ByteBuffer.wrap("Sample".getBytes()), 0, "First Write",
handler);
fileChannel.write(ByteBuffer.wrap("Box".getBytes()), 0, "Second Write",
handler);

}
}
```
25 changes: 25 additions & 0 deletions basics/java-basic/block-vs-non-blocking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
阻塞与非阻塞描述的是调用者的

如A调用B

如果是阻塞A在发出调用后要一直等待等着B返回结果

如果是非阻塞A在发出调用后不需要等待可以去做自己的事情


### 同步异步 阻塞非阻塞之间的区别

[同步异步](/basics/java-basic/synchronized-vs-asynchronization.md),是描述被调用方的

阻塞非阻塞是描述调用方的

同步不一定阻塞异步也不一定非阻塞没有必然关系

举个简单的例子老张烧水
1 老张把水壶放到火上一直在水壶旁等着水开。(同步阻塞
2 老张把水壶放到火上去客厅看电视时不时去厨房看看水开没有。(同步非阻塞
3 老张把响水壶放到火上一直在水壶旁等着水开。(异步阻塞
4 老张把响水壶放到火上去客厅看电视水壶响之前不再去看它了响了再去拿壶。(异步非阻塞

1和2的区别是调用方在得到返回之前所做的事情不一行
1和3的区别是被调用方对于烧水的处理不一样
22 changes: 22 additions & 0 deletions basics/java-basic/byte-stream-vs-character-stream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
### 字节与字符

Bit最小的二进制单位是计算机的操作部分取值0或者1

Byte字节是计算机操作数据的最小单位由8位bit组成 取值(-128-127

Char字符是用户的可读写的最小单位在Java里面由16位bit组成 取值0-65535

### 字节流

操作byte类型数据主要操作类是OutputStreamInputStream的子类不用缓冲区直接对文件本身操作

### 字符流

操作字符类型数据主要操作类是ReaderWriter的子类使用缓冲区缓冲字符不关闭流就不会输出任何内容

### 互相转换
整个IO包实际上分为字节流和字符流但是除了这两个流之外还存在一组字节流-字符流的转换类

OutputStreamWriter是Writer的子类将输出的字符流变为字节流即将一个字符流的输出对象变为字节流输出对象

InputStreamReader是Reader的子类将输入的字节流变为字符流即将一个字节流的输入对象变为字符流的输入对象
Loading

0 comments on commit 84e352a

Please sign in to comment.