day20_多线程,锁,守护线程,定时器,IO流

文章目录

  • 转换流
  • 缓冲流
  • 打印流
  • 数据流
  • 对象流
  • File
    • 递归复制
  • 程序,进程,线程
    • 线程生命周期
  • CPU
    • 并行,并发
  • 多线程
    • 线程同步-锁
  • 守护线程,定时器

转换流

OutputStreamWriter 字节输出流变成字符输出流;
InputStreamReader 字节输入流变成字符输入流;

		FileInputStream fis = new FileInputStream("");// 字节输入流
		FileOutputStream fos = new FileOutputStream("");// 字节输出流
		InputStreamReader isr = new InputStreamReader(fis);// 字节流变字符流
		OutputStreamWriter osr = new OutputStreamWriter(fos);// 字节流变字符流

缓冲流

BufferedInputStream 字节文件输入流;
BufferedOutputStream 字节文件输出流;
BufferedReader 字符文件输入流;
BufferedWriter 字符文件输出流;
缓冲流本身属于处理流,需要传入对应的流链接。

打印流

打印流是输出最方便的流,字节打印流PrintStream,字符打印流PrintWriter;PrintStream是OutputStream的子类,把一个输出流的实例传递给打印流之后,可以更加方便的输出内容,相当于将输出流重新包装。
PrintStream类的print()方法被重载很多次,可以输出不同类型的内容。
其中的setOut()提供了设置out打印路径的方法。

数据流

数据流,为了方便操作java语言中的基本数据类型和String的数据,可以使用数据流。
数据流分为DataInputStream和DataOutputStream,分别套接在InputStream和OutputStream子类的流上。
数据流输入和输出的顺序必须是一致的,读的顺序就是写的顺序。

对象流

对象流是用来存储和读取基本类型数据或对象的处理流,它可以把java中的对象写入数据源中,也能把对象从数据源中还原回来。
用ObjectOutputStream类保存基本数据类型或者对象的机制;
用ObjectInputStream类读取基本数据类型或者对象的机制。
两者不能序列化被static和transient修饰的成员变量。
创建序列化的四种方式:new;反射机制;反序列化;序列化。
反序列化就是将对象转换位二进制流的一种手段,通过序列化可以将该对象持久化存储进行传输;
序列化的对象必须实现Serializable接口,但是该接口没有任何功能,仅仅是一种标记;
序列化就是把对象持久化存储到硬盘中的过程;
反序列化就是把硬盘中的对象载入内存的过程。
如果序列化之后,我们的类文件发生了更改,每个类都有UID表示当前版本,只要更改,UID也会随着更改,如果类更改或者添加了新功能,此时如果再发生反序列化就会报错,所以一般我们会单独指定一个UID来保证版本一致。
如果不想让某个变量序列化,可以使用transient修饰符修饰,可以把没有必要序列化的变量不进行序列化操作。

File

File类:文件和文件目录路径的抽象表示,与平台无关;
它能够新建,删除,重命名文件和目录,但是file不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。
想要在java程序中表示一个真实存在的文件或者目录,那么必须有一个file对象,但是java程序中的一个file对象,可能没有一个真实存在的文件或者目录。
File对象可以作为参数传递给流的构造器。

递归复制

思路:
文件复制:本质就是输入和输出;获取指定目录下的所有子目录;整合所有后代目录和文件复制。

程序,进程,线程

程序:是为了完成特定任务,用某种语言编写的一组指令的集合,指一段静态的代码,静态对象。
进程:是程序的一次执行过程,或者是正则运行的一个程序,是一个动态的过程,有它字节的产生,存在和消亡的过程。
线程:进程可以细分为线程,是一个程序内部的一条执行路径,若一个进程同时间并行执行多个线程,就是支持多线程的;线程作为调度和执行的单位,每个线程拥有独立的运行栈或者程序计数器;一个进程中的多个线程共享相同的内存单元,他们从同一堆中分配对象,可以方位相同的变量和对象,这就使得线程间通信更加简便,高效,但是多个线程操作共享的系统资源可能带来安全隐患。

线程生命周期

JDK中用Thread.State定义了线程的几种状态。
要想实现多线程,必须在主线程中创建新的线程对象,Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中有五种状态。

  1. 新建:当一个线程类或者它子类的对象被声明或者创建的时候,新生的线程对象就处于新建状态;
  2. 就绪:当处于新建状态的线程被start后,经进入线程队列等待CPU时间片,此时它已经具备了运行的条件,只是还没有被分配CPU;
  3. 运行:当就绪的线程被调度并获得CPU资源,便进入了运行状态,run方法定义了线程的操作和功能;
  4. 阻塞:在特殊情况下,线程可能被人挂起或者进入输入输出操作,cpu会临时终止在积极的执行,进入阻塞状态;
  5. 死亡:线程完成了它全部工作被提前强制性中止或出现异常导致结束。

CPU

单核CPU是一种假的多线程,在一个时间单元内,也只能执行一个线程的任务。
如果是多核的话,才能更好的发挥多线程的效率。
一个java的应用程序,至少包括主线程,垃圾回收,异常处理线程。

并行,并发

多个CPU同时执行多个任务就是并行;
一个CPU采用时间片的形式同时执行多个任务就是并发。

多线程

多线程能够提高应用程序的响应,增强用户的体验,提高cpu的利用率,改善程序结构,将长而且复杂的进程分为多个线程,独立运行,利于理解和修改。
当程序同时执行两个或者多个任务;需要实现一些需要等待的任务的时候,需要一些在后台运行的程序的时候,可以使用多线程。
线程的创建方式有两种:创建类继承Thread类,覆写run方法,启动线程用的是start方法;实现Runnable接口,覆写run方法,启动线程,调用Thread的start方法。
线程中经常使用的方法:

  • start启动;
  • setName设置线程名字;
  • getName获取线程名字;
  • setPriority设置优先级;
  • getPriority获取优先级;
  • currentThread获取当前线程的内存地址;
  • sleep进入睡眠;
  • join等待调用线程结束再继续进行当前线程;
  • yield让出CPU,当前线程进入就绪队列;
  • isAlive判断线程是否存活。

线程同步-锁

为了防止两个任务访问相同的资源导致冲突,需要在资源被一个任务访问的时候加上锁,第一个访问某项资源的任务必须锁定这项资源,使其他任务在其被解锁前,就无法访问它。
synchronized的锁是什么?
任意对象都可以作为同步锁,所有对象都自动含有单一的锁(监视器);
同步方法的锁:静态方法(类目.class),非静态方法(this);
同步代码块:自己指定,大多时候是this或者类目.class;
必须保证统一资源的多个线程用的是一把锁,否则无法保证资源安全。
释放锁
释放锁时,当前线程的同步方法,同步代码块已经执行结束;当前线程在同步代码块,同步方法中遇到break或者return终止了代码块,方法的继续执行;
当前线程在同步代码块,方法中出现了未处理的Error或者是Exception,导致异常结束;
当前线程在同步代码块或者方法中执行了该线程的wait方法,当前线程暂停,并释放锁。
不释放锁的操作
线程执行同步代码块或者同步方法,程序调用sleep方法,yield方法暂停当前线程的执行;
线程执行同步代码块,其他线程调用了该线程的suspend方法,将线程挂起,线程不会释放锁。
Lock
比起synchronized,lock锁是显式锁,需要手动开启关闭;lock只有代码块锁,没有方法锁,使用lock能够花费较少的时间来调度线程,性能更好,并且具有更好的扩展性。
使用的方法:Lock;同步代码块(已经进入了方法体,分配了资源);同步方法(在方法体外)。

守护线程,定时器

守护线程又叫兜底线程,每个线程运行都会默认开启一个守护线程监听我们的正常程序,当没有线程执行的时候,JVM就会退出,守护线程也会推出,Thread中提供了setDaemon方法,可以设置某个线程为守护线程。
定时器:

package day20_Csdn;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 定时器
 * @author SkiMei
 *
 */
public class Day20_C2 {
     

	public static void main(String[] args) throws ParseException {
     
		// TODO Auto-generated method stub
		//创建定时器
		Timer timer = new Timer();
		String str = "2021";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
		Date date = sdf.parse(str);
		timer.schedule(new Time(), date, 100000);
		// 第一个参数是要执行的任务对象 第二个参数是执行开始的时间 第三个参数是间隔时间 
	}

}
/**
 * 创建任务继承TimerTask
 * @author SkiMei
 *
 */
class Time extends TimerTask{
     

	@Override
	public void run() {
     
		// TODO Auto-generated method stub
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
		System.out.println(sdf.format(new Date()));
	}
	
}

你可能感兴趣的:(后端,java,多线程)