IO:
Tips:我们应该从程序的角度出发,程序读入就是输入,程序数据存到外面(比如文件里)就是输出。
Tips:流是单方向的,数据只能从头到尾顺序流动一次,输入流只能用来读取数据,输出流只能用来输出数据。
学习抽象父类的公共方法,学习子类的创建方式
根据方向:输入流,输出流
根据操作单位:字节流,字符流
字节输入流:
InputStream--抽象父类--不能实例化
FileInputStream--文件字节输入流-FIS
BufferedInputStream--高效字节输入流-BIS、
FIS in = new FIS(new File(路径));
FIS in = new FIS(路径);
BIS in = new BIS( new FIS(new File(路径)));
BIS in = new BIS(new FIS(路径));
字节输出流OutputStream:
OutputStream--抽象父类,不能实例化
FileOutputStream--文件字节输出流--FOS
BufferedOutputStream--高效字节输出流-BOS
FOS out = new FOS(new File(路径));
FOS out = new FOS(路径);
BOS out = new BOS(new FOS(new File(路径)));
BOS out = new BOS(new FOS(路径));
字符输入流Reader:
Reader--抽象父类--不能实例化
FileReader--文件字符输入流-FR
BufferedReader--高效字符输入流-BR
FR in = new FR(new File(路径));
FR in = new FR(路径);
BR in = new BR(new FR(new File(路径)))
BR in = new BR(new FR(路径));
字符输出流Writer:
Writer--抽象父类,不能实例化
FileWriter--文件字符输出流--FW
BufferedWriter--高效字符输出流--BW
FW out = new FW(File/File,append/String pathname/String pathname,append);
BW out = new BW(Writer–所以传的是子类FW(上面那4种));
注意:这里的append参数表示流向文件输出数据的时候是追加还是覆盖,如果不写,默认false是覆盖,如果改为true,表示追加
字符流只能复制字符相关的文件
字节流可以复制字符,视频,音频,图片
序列化:
把内存中的对象通过序列化流输出到磁盘中(比如文件里),使用的流是ObjectOutputStream.
反序列化:
通过反序列化流将磁盘中的数据恢复成对象,使用的流是ObjectInputStream.
1.一个类的对象如果想被序列化,那么这个类必须实现可序列化接口,实现这个接口的目的是相当于给这个类做了一个标记,标记可以序列化。
2.序列化时会生成一个UID表示当前序列化输出对象的版本信息,反序列化时会拿着当前的UID与之前序列化输出的UID作比较,一致,反序列化成功,不一致,报错。
3.所以,标准操作是一次序列化对应一次反序列化,如果目标对象所在的类没有做任何修改,一次序列化也可以对应多次反序列化(根本原因是UID没变)
集合:Collection
集合可以存放多个数据,除此之外,集合的使用更加灵活并且提供丰富的方法来操作集合中的元素
泛型:
泛型通常与集合一起使用,用来约束集合中元素的类型
泛型< type >必须写引用类型而不是基本类型
泛型方法 public static ==< E > == void get(E[] e){},两处位置都出现了泛型,缺一不可
List接口
特点:1.元素都有下标
2.数据时有序的
3.允许存放重复的元素
ArrayList特点
1.底层的数据结构是数组,内存空间是连续的
2.元素有下标,通常可以根据下标进行操作
3.增删操作比较慢,查询操作比较快(数据量大时)
LinkedList特点
1.底层数据结构是链表,内存空间是不连续的
2.元素有下标,但通常首尾操作比较多
3.增删操作比较快,查询操作比较慢(数据量大时)
注意:LinkedList查询慢也不是都慢,首尾操作还是比较快的。
Map接口特点:
1.map集合的结构是:键值对,KEY与VALUE,Map.Entry
2.map中key值不允许重复,如果重复,对应的value会被覆盖
3.map中的映射关系是无序的。
4.map没有自己的迭代器,所以迭代时通常需要转成Set集合来迭代
Set接口的特点
1.Set集合没有重复的元素
2.Set集合的元素时无序的
3.Set集合可以存null值,并且null最多有一个
4.我们自定义的对象如果想去重,需要在自定义中添加重写的equals()与hasCode().
线程:
1.什么是进程?石墨是线程?有什么区别
程序:数据与指令的集合,程序是静态的。
进程:给程序加入了时间的概念,不同的时间进程有不同的状态
进程是动态的,就代表了OS中正在运行的程序。/独立性,动态性,并发性
2.什么是并行?什么是并发?
CPU:电脑的核心处理器,类似于“大脑”
并行:相对来说资源比较充足,多个CPU可以同时处理不同的进程
并发:相对来说资源比较紧缺,多个进程同时抢占公共资源,比如CPU。
3.什么是线程?线程与进程有什么关系?
线程是OS能够进行运算调度的最小单位
一个进程可以拥有多个线程,当然,也可以只拥有一个线程,只有一个线程的进程被称作单线程程序。
注意:每个线程也有自己独立的内存空间,当然也有一部分公共的空间用于保存共享的数据
4.线程有几种状态?他们是怎么转换的?
1)新建状态:new--申请PCB,进行资源的分配
2)就绪/可运行状态:万事俱备只欠CPU,其实是将创建好的线程对象加入到就绪队列中,等待OS选中,这个选择我们是控制不了的。
3)执行/运行状态:就绪队列中的线程被OS选中了,正在执行。
注意:只有就绪状态才能切换成执行状态
4)阻塞状态:线程执行中遇到了问题:
锁阻塞,休眠阻塞,等待阻塞....问题解决后再加入到就绪队列中
5)终止状态:线程成功执行完毕,释放资源
5.如何判断程序有没有线程安全问题?
在多线程程序中+有共享数据+多条语句操作共享数据
同步:体现了排队的效果,同一时刻只能有一个线程独占资源,其他没有权利的线程排队。
坏处就是效率会低。不过保证了安全。
异步:体现了多线程抢占资源的效果,线程间互相不等待,互相抢占资源
坏处就是有安全隐患,效率要高一些
同步锁 synchronized:
格式:synchronize(唯一的锁对象){可能出现数据安全问题的所有代码}
使用同步锁的注意事项:
1.锁对象必须唯一
继承的方式,常用的锁对象是类名.class字节码对象
2.锁对象的类型不做限制,只要能保证唯一即可。
3.加锁的范围不能太大,也不能太小,太大浪费效率,太小锁不住
线程池 ExecutorService
Executors是用来辅助创建线程池的工具类对象
常用方法是 newFixedThreadPool(int)
这个方法可以创建指定线程数目的线程池对象
创建出来的线程池对象时ExecutorService:用来存储线程的池子,负责:新建/启动/关闭线程
execute()让线程池中的线程来执行业务,每次调用都会将一个线程加入到就绪队列中。
注意:线程池负责将线程加入到就绪队列中,但并不代表所有的线程都会运行,线程能否执行还是取决于OS的调用,如果没有被分配时间片,是转换不了预习状态的。
注意:线程池是不关闭的,主要就是想实现线程的随取随用,这样就避免了频繁的创建与销毁线程,浪费大量资源。