forked from hollischuang/toBeTopJavaer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
hollis.zhl
committed
Jun 1, 2019
1 parent
baa1ff4
commit 84e352a
Showing
15 changed files
with
627 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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对象载入。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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来动态代理目标类。 | ||
|
||
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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。 | ||
|
||
### 区别及联系 | ||
|
||
BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。 | ||
|
||
NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。 | ||
|
||
AIO ( Asynchronous 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); | ||
|
||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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的区别是,被调用方对于烧水的处理不一样。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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类型数据,主要操作类是OutputStream、InputStream的子类;不用缓冲区,直接对文件本身操作。 | ||
|
||
### 字符流 | ||
|
||
操作字符类型数据,主要操作类是Reader、Writer的子类;使用缓冲区缓冲字符,不关闭流就不会输出任何内容。 | ||
|
||
### 互相转换 | ||
整个IO包实际上分为字节流和字符流,但是除了这两个流之外,还存在一组字节流-字符流的转换类。 | ||
|
||
OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流输出对象。 | ||
|
||
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象。 |
Oops, something went wrong.