BufferInputStream 将建立一个内部的缓冲区数组,内部缓冲区数组将根据须要从包含的输入流中从新填充,一次能够读取多个字节html
BufferOutputStream 该类实现缓冲输出流。 经过设置这样的输出流,应用程序能够向底层输出流写入字节,而没必要为写入的每一个字节致使底层系统的调用java
构造方法:传入字节流,能够指定缓冲区大小数组
bos.write("hello\r\n".getBytes(StandardCharsets.UTF_8));安全
BufferedOutputStream 内部带有缓冲区 写数据的时候 先写出到缓冲区,缓冲区写满的时候 ,才会将缓冲区的内容写出到磁盘 调用flush方法 只刷新缓冲流 但不释放资源 close方法 在关闭流 释放资源以前 会先刷新缓冲流网络
为何缓冲流的构造方法中须要的是一个字节流,而不是具体的文件或者路径呢?多线程
字节缓冲流仅仅提供缓冲区,而真正的读写数据还的移开基本的字节流对象进行操做。并发
因为字节流操做中文不是特别方便,因此就出现了字符流jvm
字符流 = 字节流 +字符集ide
中文字节存储方式编码
用字节流复制文本文件时,文本文件也会有中文,可是没有问题,缘由就是最终底层操做会自动的进行字节拼接成中文。
如何识别中文?
汉字在存储的时候 不管使用那种编码存储 第一个字节都是负数。
编码就指的是将字符转换成字节
string.getBytes(),参数可指定String 字符集名
默认的编码 UTF-8
// 解码 编码和解码必须使用相同的码表 不然会出现中文乱码
解码: 将字节数组转换为字符
String(byte[] bytes, String charsetName)构造一个新的String由指定用指定的字节的数组解码
字符流的抽象基类:
Reader 字符输入流的抽象基类 编码
Writer 字符输出流的抽象基类 解码
字符流中和编码相关的类:
InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset
将其解码为
OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节
构造方法:字节流+可选字符集名
使用字符流完成对于中文的写和读
写:write(字符数组/字符串/字符,起始位置)
刷新和关闭close(),flush()
读:read(字符/字符数组,起始位置)
字符流自带缓冲区
FileReader 是InputStreamReader的简洁形式
FileWriter 是OutputStreamReader的简洁形式
BufferedReader
从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。能够指定缓冲区大小,或者可使用默认大小。
BufferedReader(Reader in)
建立使用默认大小的输入缓冲区的缓冲字符输入流。
readline()读一行
BufferedWriter
将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
能够指定缓冲区大小,或者能够接受默认大小。
BufferedWriter(Writer out)
建立使用默认大小的输出缓冲区的缓冲字符输出流。
newLine()写分隔符
字节流能够赋值文件数据,有四种方式通常采用字节缓冲流一次去屑一个字节数组的形式。
PrintStream:err、out
InputStream:in
public static void main(String[] args) throws IOException { //字节流 InputStream is = System.in;// 字节输入流的数据来源来自标准输入设备键盘 BufferedReader br = new BufferedReader(new InputStreamReader(isr)); System.out.println("请输入一个整数:"); int i= Integer.parseInt(br.readLine()); System.out.println("您输入的整数为:"+(i + 1)); //以上代码就是本身实现了键盘录入字符串和整数的方法 这样写起来有点麻烦,所以Java提供了 Scanner sc = new Scanner(System.in); }
PrintStream ps = System.out;
打印流分为:
字节 打印流 PrintStream
字符打印流 PrintWtriter
打印流的特色:
只负责数据的输出 不能读取数据
有一些特有的方法 println() print()
对象序列化: 就是将对象保存到磁盘或者在网络中传输对象 为了对象保存的正确性 和传输的安全性,须要对对象进行编码处理,那么把这种处理方式称为对象的序列化
反序列化:将序列化的对象解析为原对象的过程 就称为反序列化
ObjectOutputStream oos.writeObject(obj);
ObjectInputStream ois.readObject();再强制转型
对于对象传输 对象必须实现java.io.Serializable接口
Porperties是Map集合的一个实现类
Properties prop = new Properties(); prop.put(k,v); prop.entrySet();
Porperties能够保存到流中或者从流中加载。 属性列表中的键及其对应的值都是字符串
prop.getProperty(k) prop.setProperty(k,v)
prop.load(输入字节流/reader) prop().store(输出字节流/writer,注解默认为null)
程序: 是为了完成特定任务 用某种语言编写的一组指令的集合。指的一段静态。
进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程:有他自身的产生 存在 以及消亡的过程--生命周期
程序是静态的 进程是动态的。进程做为资源分配单位,系统在运行时会为每一个进程分配不一样的内存区域。
线程(thread) 进程进一步细化就是线程,是一个程序内部的一条执行路径。
若一个进程同一时间并行执行多个线程,就是支持多线程。
线程做为调度和执行的单位,每一个线程拥有独立的运行栈和程序计数器,线程的切换开销比较小。
一个进程中的多个线程共享相同的内存单元和内存地址空间,他们从一个堆中分配对象,能够访问相同的变量和对象。这就是的线程间的通讯变得简便和高效。但多个线程操做共享的系统资源可能会带来安全隐患。
单核CPU和多核CPU
在java中 一个程序至少有三个线程组成, 主线程(main) 垃圾回收线程(gc) 异常处理线程。
并行和并发:
并行:多个CPU同时执行多个任务
使用多线程的优势:
1 提升了应用程序的响应。
2 提升了计算机CPU的利用率
3 改善程序结构。
什么时候须要多线程?
程序须要同时执行两个或多个任务
程序须要实现一些须要等待的任务的时候:如:用户输入,文件读写 网络操做等。
须要一些后台运行的程序时
建立一个新的执行线程有两种方法。
一个是将一个类声明为Thread
的子类。 这个子类应该重写Thread的run方法 。 而后能够分配并启动子类的实例
另外一种方法来建立一个线程是声明实现类Runnable
接口。 那个类而后实现了run
方法。 而后能够分配类的实例,在建立Thread
时做为参数传递,并启动
为何要重写run方法?
由于run方法是用来封装被线程执行的代码的。
run方和start方法的区别?
run()封装了线程执行的代码,直接调用的,至关于普通方法调用。
start方法 启动线程,而后由jvm调用此线程的run方法
public interface Runnable
Runnable
接口应由任何类实现,其实例将由线程执行。 该类必须定义一个无参数的方法,称为run
Runnable r = new MyRannable(); Thread t1 = new Thread(r);
t1.start();
或 new Thread(new Runnable(){@Override public void run(){sout;} }).start();
Thread(name):有参构造,参数是线程的名字
th.setName(name);
Thread.currentThread();返回当前正在执行的线程对象的引用。
th.getName();
th.getPriority();
th.setPriority(pri);
每一个线程都有优先权。 具备较高优先级的线程优先于优先级较低的线程执行
线程的两种调度模型
分时调度: 全部线程轮流实现CPU的使用权,平均分配每一个线程占有CPU的时间片
抢占式调度: 优先让优先级高的线程使用CPU,若是线程的优先级相同,那么会随机选择一个。优先级高的线程得到CPU执行权的几率更高。
java是的是抢占式的调度模型。
线程的默认优先级为5,线程的优先级的范围为1(小)--10(大)