Java Learn(十五)

I/O流、线程

I/O流

ObjectOutputStream 类

基本概念
  1. java.io.ObjectOutputStream 类用于将 Java 语言的整个对象一次性写入到输出流中。
  2. 只能将支持 java.io.Serializable 接口的对象写入流中
  3. 类通过实现 java.io.Serializable 接口以启用其序列化功能
  4. 序列化就是指将一个对象中需要保存的各种数据有效组织成一个字节序列的过程
常用方法

ObjectOutputStream(OutputStream out) — 根据参数指定引用构造对象

void writeObject(Object obj) — 用于将参数指定的对象写入输出流中

void close()

ObjectInputStream 类

基本概念

java.io.ObjectInputStream 类用于将之前写入的整个对象一次性读取出来

常用方法

ObjectInputStream(InputStream in) — 根据参数引用构造对象

void readObject() — 用于读取对象并返回

void close()

分享经验:

当需要向文件中写入多个对象时,建议将多个对象放入一个集合中,然后将集合看做一个整体写入文件,此时再读取文件中所有内容时,只需要读取一个集合即可。

线程的基本概念和基本操作

基本概念
  1. 程序 — 主要指存在放硬盘上的可执行文件,数据结构+算法;
  2. 进程 — 主要指运行在内存中的程序;
  3. 目前主流的操作系统都支持多进程,为了让操作系统同时执行多个任务,当进程是重量级的,新建进程对 CPU 和内存等资源的消耗比较大。
  4. 线程是进程内部的程序流,也就是操作系统支持多进程,当每个进程内部又可以支持多线程,而且线程是轻量级的,新建线程会共享所在进程的资源,因此资源消耗比较小。
  5. 以后主流的开发都是多线程技术,而操作系统采用时间片轮转法来实现多线程的并发执行,所谓并发就是指宏观并行微观串行的技术。

基本操作

Thread 类
  1. java.lang.Thread 类用于描述线程,而 java 虚拟机允许启动多个线程执行。
  2. 创建并启动线程有两种方式:
    a.自定义类继承 Thread 类并重写 run() 方法,创建该类的对象去调用 start() 方法。
    b.自定义类实现 Runnable() 接口并重写 run() 方法,创建该类的实例作为 Thread() 类构造方法的实参,然后调用 Thread() 类的对象去调用 strat() 方法。
创建线程的相关方法

hread()— 无参形式构造对象;

hread(String name)— 根据指定的名称构造对象;

hread(Runnable target)— 根据接口的引用来构造对象;

hread(Runnable target, String name)— 根据引用和名称来构造对象;

oid run()— 没有使用 Runnable 接口构造的线程对象调用该方法什么都不做;

— 使用 Runnable 接口作为参数构造的线程对象调用该方法的结果就是调用 Runnable 接口中的 run() 方法

oid start()— 用于启动线程,会自动调用该线程对象中的 run() 方法。

多线程的原理分析
  1. main() 方法是程序的入口,执行 main() 方法的线程叫主线程;
  2. 在 main() 方法通过 start() 方法启动的线程叫做子线程/新线程;
  3. 对于 start() 方法之前的代码来说由主线程执行一次,当 start() 方法调用成功之后,线程的个数立刻由1个变成2个,其中主线程继续向下执行,子线程去执行 run() 方法中的代码,此时两个线程各自独立运行,从而实现交错打印的效果。
  4. 当 run() 方法执行结束后子线程结束,当 main() 方法执行结束后主线程结束,两个线程没有明确的先后执行次序,由操作系统的调度.

注意:

继承的方式代码相对简单,但是 Java 语言只支持单继承,若继承 Thread 类则无法继承其他类,而实现接口的方式代码相对复杂,但不影响该类继承或实现其他类或接口,推荐第二种方式,从而提高代码的可维护性。

线程的名称和编号

long getId() — 用于获取线程的编号并返回

String getName() — 用于获取线程的名称并返回

void setName(String name) — 用于设置线程的名称为参数指定的数据

static Thread currentThread() — 用于获取当前正在执行线程的引用并返回

线程的主要状态

新建状态 — 当使用 new 运算符创建出来的线程所在的状态

— 此时线程还没有开始执行

就绪状态 — 当线程对象调用 start() 方法后进入的状态

— 此时线程还没有开始执行

运行状态 — 当线程被线程调度器调度起来之后进入的状态

— 此时线程开始执行

— 当线程时间片执行完毕后任务没有完成就回到就绪状态

消亡状态 — 当时间片执行完毕任务已经完成后消亡中转台

阻塞状态 — 当线程在执行过程中发生了阻塞事件进入的状态,如 sleep() 方法

— 当阻塞事件结束后回到就绪状态