IO/多线程

IO

file类

java.io.file类:文件和目录路径名的抽象表示形式,和平台无关

file能新建、删除、重命名文件和目录,但不能访问文件内容本身,需要访问文件内容本身,需要使用输入/输出流

io流

io流用来处理设备之间的数据传输

Java程序中,对于数据的输入\输出操作以流(stream)的方式进行

流的分类

按数据单位:字节流(8bit)、字符流(16bit)

按数据流的流向:输入流、输出流

复制文件

//创建一个输入流
    FileInputStream io = new FileInputStream(intPath);
//创建一个输出流
    FileOutputStream ou = new FileOutputStream(outPath);
//创建一个缓冲数组,来接收流的数据
    byte[] b = new byte[1];
//设置长度记录数据
    int len = 0;
//循环,当数据没输入完时,输出数组b中的数据
    while((len=io.read(b))!=-1){
        ou.write(b,0,len);
    }

     ou.flush();
     ou.close();
     io.close();

文件流是计算机和硬盘之间发生的io操作,读写速度较慢。

为了绕过硬盘的读写速度限制,Java提供一种基于内存的缓冲流Buffered

反射Reflection

反射是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection取得任何类的内部信息,并能直接操作任意对象的内部属性及方法

功能:

  1. 运行时判断任意一个对象所属的类
  2. 运行时构造任意一个类的对象
  3. 运行时判断任意一个类所具有的成员变量和方法
  4. 运行时调用任意一个对象的成员变量和方法
  5. 生成动态代理

反射可以得到的信息:某个类的属性、方法和构造器,某个类到底实现了那些接口。

对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息

  • Class本身也是一个类

  • Class对象只能由系统建立对象

  • 一个类在JVM中只会有一个Class实例

  • 一个Class对象对应的是一个加载到JVM中的一个.class文件

  • 每个类的实例都会记得自己是由哪个Class实例生成

  • 通过Class可以完整地得到一个类中的完整结构

反射获得Class实例

对于Person p = new Person()这个类来说

  1. 知道类名

    Class c0 = Person.class;
    
  2. 知道类的一个实例对象

    Class c1 = p.getClass();
    
  3. ***知道Class实例的类的全路径(包名.类名)

    Class c2 = Class.forName("包名.Person")
    

多线程

程序、进程、线程

程序Program

程序是为完成特定任务,用某种语言编写的一组指令的集合。即一段静态的代码,静态对象。

进程Process

进程是程序的一次执行过程,或是正在运行的一个程序,动态过程:有它自身的产生、存在和消亡的过程

程序是静态的,进程是动态的

线程Thread

进程可进一步细化成线程,是一个程序内部的一条执行路径

若一个程序可同一时间执行多个线程,就是支持多线程的。

多线程

一个进程(一个程序执行期间),可以分化为并行执行多个线程(多个子程序)

  1. 继承Thread类

    • 每个线程都是通过某个特定的Thread对象的run()方法来完成操作的,经常把run()方法的主体称为线程体

    • 通过该Thread对象的start()方法来调用这个线程

      实现过程

      1. 定义子类继承Thread类
      2. 重写Thread类中的run方法
      3. 创建(new)Thread子类对象,即创建了一个线程对象
      4. 调用线程对象的start方法,启动线程,调用run方法

    并行:我们发现开启start方法后,主程序的main方法和线程的run方法是同时运行的,不存在先后关系,就像一条河流开启了一个支流,他们是同时流动的。

run()方法:多线程要执行的线程体

start()方法:开启线程,执行run()方法里的线程体

  1. 实现Runnable接口

线程方法

  1. yield()线程让步
  2. join()线程插入
  3. sleep()线程睡眠
  4. stop()线程结束
  5. start()线程启动
  6. getName()返回线程名称
  7. currentThread()返回当前线程

线程的生命周期

线程的生命周期有五种状态

线程的状态

  1. 新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
  2. 就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已经获取到了所需的资源,具备了运行的条件
  3. 运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能
  4. 阻塞:在某种特殊情况下,被认为挂起或执行输入输出操作时,让出CPU资源并临时中止自己的执行,进入阻塞状态
  5. 死亡:线程完成了它的全部工作或者线程被提前强制中止

安全问题

出现原因

当多个线程的多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。

解决办法

对多条操作共享数据的语句,只能让一个线程都执行完,再执行过程中,其他线程不可以参与执行

同步机制

Synchronized

posted @ 2021-07-05 20:56  灰线  阅读(742)  评论(0)    收藏  举报