继承关系:
Object父类
Closeable Readable 父接口。
构造器:
构造器都是protected,专门给子类设计。(抽象类)
方法:
read() 读取字符。
close() 关闭流。
继承关系:
Object父类
closeable, Flushable, Appendable 父接口。
构造器:
方法:
append()方法
close()关闭流
flush()刷新
write()写字符
OutputStreamWriter
继承关系:继承Writer
构造器:
OutputStreamWriter(OutputStream out) :要基于OutputStream对象来创建。
InputStreamReader
继承关系:继承Reader
构造器:
InputStreamReader(InputStream in) :要基于InputStream对象来创建。
java中流的分类,还可以按照是否基于别的流创建对象:
不基于别的流创建对象:节点流
基于别的流创建对象: 处理流
继承关系:继承Reader
构造器:BufferedReader (reader) 基于别的Reader对象,来创建。
注意:这里我们可以看到很多的流在实现功能增强时,采用了一种俄罗斯套娃形式,逐步实现了对内层流功能的增加。这种代码的编写格式就是装饰模式。
BufferedWriter和BufferReader相类似
BufferReader已实现了字节到字符转换的麻烦,下面两个也已实现了字节到基本数据类型数值的转换
DataInputStream
继承关系:FilterInputStream
接口:closeable,DataInput
DataOutpuStream
继承关系:FilterOutputStream
接口:Closeable, Flushable, DataOutput
ObjectInputStream/ObjectOutputStream
WriteObject():将对象写入输出流中
ReadObject():从 ObjectInputStream 读取对象
将对象转化为流:序列化。
将流转化为对象:反序列化。
1.transient 临时会属性,让对象在序列化时,此属性不被序列化。
如果被transient修饰的属性,我们想要序列化他怎么办?
2.自定义序列化方法:
这两个方法写法固定,而且并没有用过接口来规范,所以我们通常从api中拷贝出来:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException ;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
他们writeObject负责对象的序列化:序列化属性。
readObject负责对象的反序列化:取出我们保存的属性。
3.自定义序列化接口:
如果我们忘记了上面方法的写法,又必须实现自定义序列化:
Externalizable 自定义序列化接口:
writeExternal() ;
readExternal() ;
如果序列化和反序列化发生在了两个程序中,这个时候,java是要求我们必须显示地为序列化类型设置一个UID:
static final long serialVersionUID = 42L;
进程:在每个系统中,每个系统有自己独自的定义。通常来讲进程就代表一个程序。
线程:线程是代码的执行流程。我们程序启动,会创建一个进程,在这个进程中通常都会带有一条线程,这条线程会找到main方法,并从main开始逐条执行我们的语句。
注意:
- 在java中,我们没有一个明确的api专门负责操作进程。这个java是通过JNI技术通过native方法调用本地api来执行的。
- 一个进程中可以拥有多条线程。
Thread 和 Runnable
Thread类是Java对线程的描述。
Runnable接口是Java对线程任务的规范,其中有run()方法,线程所有执行的任务都要在run()方法里
方式1:创建Thread对象,创建Runnable的子类型实现run方法,Thread启动线程start(),并回调run方法
方式2:实现Thread类型的的子类型,并扩展run方法,再由Thread启动线程start()
- 当线程的任务执行完毕,自动销毁
- stop()和destory()方法终止线程,但不推荐
- 抛出异常
正常来说我们要停止线程,我们采用方法1,让run方法中的任务执行完毕,线程自动销毁。
让出cpu的执行权,然后重新去获取。
相关方法
getPriority():获取该线程的优先级
setPriority():设置该线程的优先级
使线程进入“睡眠”状态。在规定的时间内,这个线程是不会运行的。同时让出CPU
线程都是同时执行的,如果有两条线程,要实现一条线程A先执行,另一条线程B再执行,可以在B线程中调用A.join(),从而实现B等待A执行完毕,再执行。
当多条线程对同一个数据进行操作时,可能发生数据同步问题。所以我们需要多个线程处理一个数据时,同时只允许一条线程对数据进行操作,执行完毕后,交由后面等候的一条线程执行。
java中提供了一个由对象实现的互斥锁,我们可以通过锁将数据进行保护,保证同一时刻,只有一条线程能操作。
锁的使用:
1.java中所有对象都持有一把同步锁。不同对象的同步锁不会互相作用。
2.多条线程要实现同步操作,必须基于同一个对象的锁实现,锁代码块,才能起作用。
锁的方式:
synchronized(锁对象){
锁住的代码。
}
public synchronized void func(){
锁住的代码。//锁方法是锁的this对象。
}
wait(): 锁语句块中,让线程停止。
notify() /notifyAll():在同一个锁的语句块中,让wait停止的线程重新启动。
notify()是唤醒在这个对象上等待的一条线程(随机),notifyAll()是唤醒在这个对象上等待的所有的线程。
作用:
让一条线程在一个对象A上等待(停止),需要唤醒时,由另一条线程调用对象A的唤醒方法,来唤醒在对象上等待的那条线程。
注意:
这两个方法都是Object的方法,虽然是作用于Thread,但是由于实现是基于对象来实现的,所以他们是Object的方法。