# 前言
IO:
a. 转换流:进行字符和字节之间的转换
b. 系统流:都是System类中的对象,本质上是字节流
c. 打印流:只有输出没有输入,提供了便捷的打印和换行的操作
d. 合并流:将多个字节输入流合并成一个字节输入流;在合并的时候需要将这多个字节流放入一个Enumeration中
e. 序列化/反序列化:
i. 序列化 - 将对象转化为字节数组 ii. 反序列化 - 将字节数组还原回对象 iii. 一个接口 - Serializable,两个关键字 - static/transient,一个属性 - serialVersionUID iv. 允许对集合进行整体的序列化RandomAccessFile:
a. 双向流,可以对文件进行读写操作
b. 在操作文件的时候是把文件看做一个大型的字节数组
c. 在使用的时候需要指定模式
Properties:
a. 是一个可以持久化的映射
b. 键和值默认都是String
c. 在持久化的时候要求数据必须持久化到properties文件中
d. properties文件的编码默认是西欧编码,所以如果存入中文会自动转化为对应的utf-16的编码
e. 经常作为配置文件使用
断言:
a. 格式:assert 判断条件 : 提示信息;
b. 根据已知条件来对结果进行预判
c. 在Java中,断言默认是不开启的,所以需要手动添加参数-ea
单元测试:
a. 在使用的时候需要导入测试库Junit4
b. 三无:无参、无返回值、非静态
c. @Test, @Before, @After
静态导包:
a. 格式:import static 包名.类名.静态方法名;
b. 优点:优先加载指定的静态方法,来提高运行效率
c. 缺点:书写麻烦、可读性不强、方法签名一致的方法
# 线程
一、概述
进程:当前操作系统执行的任务
一般而言,现在操作系统都是多进程的
线程:进程中的子任务
在实际应用中,都是多线程的场景
线程本身是在CPU上执行,CPU的每一个核在同一时刻内只能执行一个线程,但是CPU在底层会对线程进行快速的轮询切换
每一个进程中至少包含1个线程
线程在执行任务的过程大概可以分为2大块:
a. 在CPU上执行
b. 和计算机的硬件进行交互。当线程和硬件进行交互(例如读取文件)是不占用CPU的
多线程的意义:提高CPU利用率。理论上,当线程个数足够多的时候,
CPU的利用率是能够到达100%
- 主函数所在的类默认是一个单独的线程
二、定义线程
继承Thread,重写run方法,将要执行的逻辑放到run方法中,然后创建 线程对象调用start方法来开启线程
实现Runnable,重写run方法,然后利用Runnable对象来构建Thread对象 调用start方法来启动线程
实现Callable<T>,重写call方法 --- 在现阶段仅作了解
三、多线程的并发安全问题
线程之间是相互抢占执行,而且抢占是发生在线程执行的每一步
由于线程的抢占而导致出现了不合理的数据的现象 - 多线程的并发安全问题
四、线程中的锁机制
为了解决线程并发问题,引入了synchronized代码块 - 同步代码块
同步代码块需要一个锁对象
锁对象:要求被当前的所有线程都认识 - 共享资源、方法区中的资源、this
this作为锁对象的时候,要求利用同一个Runnable对象来构建不同的Thread对象
同步:在同一时刻内资源/逻辑只被一个线程占用/执行
异步:在同一时刻内资源/逻辑可以被多个线程抢占使用
同步一定安全,不安全一定是异步
由于多个线程之间的锁形成了嵌套而导致代码无法继续允许,这种现象 称之为死锁
现阶段,只能尽量避免死锁。实际开发中,会做死锁的检验;如果真的 出现死锁,会根据线程的优先级打破其中一个或者多个锁
五、线程的优先级
将线程的优先级分为1-10一共十个等级
理论上,数字越大优先级越高,那么该线程能抢到资源的概率就越大
实际上,相邻的两个优先级之间的差别非常不明显;如果想要相对明显
一点,至少要相差5个优先级
六、等待唤醒机制
利用标记位以及wait、notify、notifyAll方法来调节线程之间的执行顺序
wait、notify、notifyAll和锁相关,用哪个对象作为锁对象使用,那么就用该锁对象来调用wait、notify
七、线程的状态
八、守护线程
守护其他的线程,只要被守护的线程结束,那么守护线程就会随之结束
一个线程要么是守护线程要么是被守护的线程
守护线程可以守护其他的守护线程
在Java中,最常见的一个守护线程是GC
总结:sleep和wait
sleep:在使用的时候需要指定休眠时间,单位是毫秒,到点自然醒。在无锁状态下,会释放CPU;在有锁状态下,不释放CPU的。sleep方法是 设计在了Thread类上,并且是一个静态方法
wait:可以指定等待时间也可以不指定。如果不指定等待时间则需要被 唤醒。wait必须结合锁来使用,当线程在wait的时候会释放锁。wait方法是设计在了Object类上
总结:线程产生的场景
系统自启
用户请求
线程之间的启动
总结:线程结束的场景
寿终正寝:线程自然结束
他杀:被其他线程kill
意外:线程因为报错崩溃而退出
扩展:方法区和线程的关系
类是存储在方法区中,方法区被所有的线程共享的空间
每一个线程独有一个栈内存
单例模式
一、概述
在全局过程中只存在一个对象
饿汉式:在定义对象的时候将这个对象进行了初始化
懒汉式:将对象的初始化过程推后
懒汉式相对饿汉式而言,将对象的初始化过程推后,提高了类的加载速率,但是存在线程安全问题;饿汉式是线程安全的
扩展作业:了解单例模式的七种方式