1.IO流
I---input 输入(从程序外---输送到 ---程序里)
O---Output 输出(从程序里---输送到 ---程序外)
流(管道):输送方法。
2.介绍File 工具类:
“万事万物皆对象”
----1.分析参与者,文档对象。----提取一个类,确定类名 --File
2.分析参与者的属性
3.分析参与者的行为。
[File类提供的方法,都是用来获得文件/目录的基本信息,
没有提供读写文件中内容的方法,可以通过IO流来解决]
3.介绍IO流 读写文件:
IO流的分类:
【根据流的方向:】分为输入流 输出流
【根据流承载信息量的大小:】分为字节流 字符流
【根据流的功能:】分为节点流和处理流
4.使用io流进行文件信息的读写:
字节输入流 字节输出流====图片复制
字符输入流====读取文件里的汉字内容。
字符输出流====模拟微信聊天信息存储功能:
-------以上所有流 都是 节点流。
节点流:只有输入输出的功能;直接连接信息源对象的
处理流:有输入输出,还拥有其他的功能;连接节点流对象的
----介紹处理流----
缓冲流(自带缓冲区)System.out
转换流(可以将字节流---》字符流)
对象流(内存对象---文件里)
数据流(在存取信息的时候,可以保留信息类型)
打印流(了解,)
5.”多线程“:
概念:
程序:具有一定功能的代码的集合,但是是静态的,没有启动运行
进程:启动运行的程序【资源的分配单位】
线程:进程中的每一条执行路径,就是线程。
概念:
并行:多个CPU同时执行多个任务
并发:一个CPU“同时”执行多个任务(采用时间片切换)
将1分钟---分成10000份==1毫秒
5.1 创建多线程3种方式:
【第一种:继承父类】
1.创建线程类: public class NumberThread extends Thread
2.创建线程对象:【新生状态】
NumberThread num=new NumberThread();
3.【就绪状态】--cpu给你资源-- 》运行状态
num.start();
【售票例子】
有10张车票,3个窗口,同时售票,显示售票结果。
优点:启动线程对象 高效率;
缺点:占用了 父类位置
【第二种:实现接口】
创建类:public class Window implements Runnable {}
创建对象:
Window w1=new Window();
Thread t1=new Thread(w1,"第1");
t1.start();
优点:没有占用了 父类位置 ;共享资源的能力强,资源不用加static
缺点: 启动线程对象 高效低;
【第三种:实现接口】
学习第三种原因:
run()有不足的地方: 返回值是 void , run()不让抛出异常。
5.2 线程对象的常用方法:
a.getName() 获得当前线程对象的名字
---如果开发者使用了,无参构造器,程序自动设置线程名 Thread-0++(主线程除外)
---开发者使用,有参构造器,参数的值就是线程的名字。
---借助num.setName("线程1");为线程名赋值。
b.currentThread() 获得当前正在运行的线程对象。
c. t2.setPriority(1);//设置线程的优先级 1-10之间,默认5
d.Thread.currentThread().stop();//过期方法,不建议使用
线程死亡
e。强行抢占cpu资源
num.join(); join方法:当一个线程调用了join方法,这个线程就会先被执行,它执行结束以后才可以去执行其余的线程。
for (int i = 1; i <=100 ; i++) {
System.out.println(Thread.currentThread().getName()+"i="+i);
if(i==50){
num.join();
System.out.println("maini=50");
}
}
f.setDaemon(true); 伴随线程
tt.setDaemon(true);//设置伴随线程
主线程死亡,伴随线程也会跟着一起死亡。
g. sleep(毫秒);设置线程休眠。
5.3 线程的生命周期:
使用线程构造器---创建线程对象====》线程新生状态
线程对象.start()====>进入到 就绪状态【有资格,没资源】
线程对象.run()====>进入到 运行状态【有资格,有资源】----在时间片段内 ,执行完----死亡状态
----在时间片段内 ,没执行完----重回就绪状态
----在时间片段内 ,出现突发事件---阻塞状态---就绪状态
5.4 线程安全问题:
【第一种:同步代码块】
synchronized (WindowThread.class) { //WindowThread.class 监视器对象==锁子
if (ticket >= 1) {
System.out.println(getName() + "窗口,卖出第" + ticket + "票");
ticket--;
}
}
【第二种:同步方法】
public static synchronized void buyTicket(){ /*synchronized 锁子 this当前线程对象。 */
if (ticket >= 1) {
System.out.println(Thread.currentThread().getName() + "窗口,卖出第" + ticket + "票");
ticket--;
}
}
【第三种:】
static Lock lock=new ReentrantLock();//创建lock锁对象
@Override //【lock锁】
public void run() {
while (true) {
lock.lock();//上锁
if (ticket >= 1) {
System.out.println(getName() + "窗口,卖出第" + ticket + "票");
ticket--;
}
lock.unlock();//解锁
if (ticket == 0) {
break;
}
}
}
下面依旧是笔记,与上面略有不同
package com.jr.biji;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BiJi729 {
/*
1,IO流
I--input输入(从程序外--输送到--程序里)
O--Output输出(从程序里--输送到--程序外)
流(管道):是一种输送方式
2,介绍file工具类:
“万事万物皆对象”
---1,分析参与者(文档对象)---提取一个类,确定类名--file
2,分析参与者的属性
3,分析参与者的行为---不是特别关注file类的行为
【file类提供的方法,都是用来获得文件/目录的基本信息,没有提供读写文件中内容的方法,可以通过IO流来解决】
3,介绍IO流 读写文件:
IO流的分类:
根据流的方向:分为输入流和输出流
根据流承载信息量的大小:分为字节流,字符流(字节流无法处理汉字,字符流可以)
根据流的功能:分为节点流(只有输入输出功能),处理流
4,使用IO流,进行文件信息的读写:
字节输入流 字节输出流----图片复制
字符输入流---读取文件里的汉字内容
字符输出流---
----以上所有流都是节点流(只有输入输出功能)
5,介绍处理流---
节点流只有输入输出的功能,直接连接信息源对象
处理流有输入输出功能,还有其他功能 连接节点流对象
缓冲流:自带缓冲区
转换流(可以将字节流转换为字符流,单向转换)
对象流(内存对象---文件里)
数据流(在存取信息的时候,可以保留信息的类型)
打印流(了解,System。out)
二,多线程:
1,程序,进程,线程
程序(program):是为完成特定任务、用某种语言编写的一组指令的集合,是一段静态的代码。(程序是静态的)
具有一定功能的代码的集合,但是是静态的,没有启动运行
进程(process):是程序的一次执行过程。正在运行的一个程序,进程作为资源分配的单位,在内存中会为每个进程分配不同的内存区域。 (进程是动态的)是一个动的过程 ,进程的生命周期 : 有它自身的产生、存在和消亡的过程
启动运行的程序【资源的分配单位】
线程(thread),进程可进一步细化为线程, 是一个程序内部的一条执行路径。若一个进程同一时间并行执行多个线程,就是支持多线程的。
进程中的每一条执行路径,就是线程
2,并行,并发
并行:多个CPU同时执行多个任务
并发:一个CPU“同时”执行多个任务(采用时间片切换)
将一分钟---分成10000份=6毫秒
3,创建多线程的方式:
线程类:只有线程类才有能力开辟一条新线程
第一种方式:继承父类
优点:启动线程对象高效率
缺点:占用了父类位置
1,创建线程类:public class NumberThread extends Thread
2,创建线程对象:【新生状态】
NumberThread num=new NumberThread();
3,【就绪状态】- (只能等CPU给资源) -->运行状态
num.start();
第二种方式:实现接口
创建类:public class Window implements Runnable
创建对象:
Window w1=new Window();
Thread t1=new Thread(w1,"第一");
t1.start();
Thread t2=new Thread(w1,"第二");
t2.start();
Thread t3=new Thread(w1,"第三");
t3.start();
优点:没有占用父类位置,共享资源能力强,不用加静态
缺点:启动线程对象,效率低
第三种方式:实现接口
第二种方式有不足(run()方法):
没有返回值
run()不能抛出异常
4,线程对象的常用方法:
1,getName()获得当前线程对象的名字
---线程名:
如果开发者使用了无参构造器,程序自动设置线程名--->(命名规则)Thread-0++(主线程名不遵循该命名规则)
开发者使用有参构造,参数的值就是线程的名字
借助num.setName();为线程名赋值
2,currentThread() 获得当前正在运行的线程对象。
3,t2.setPriority(1);//设置线程的优先级 1-10之间,默认5
4,Thread.currentThread().stop();//过期方法,不建议使用
线程死亡
5,强行抢占cpu资源
num.join(); join方法:当一个线程调用了join方法,这个线程就会先被执行,它执行结束以后才可以去执行其余的线程。
for (int i = 1; i <=100 ; i++) {
System.out.println(Thread.currentThread().getName()+"i="+i);
if(i==50){
num.join();
System.out.println("maini=50");
}
}
6,setDaemon(true); 伴随线程
tt.setDaemon(true);//设置伴随线程
主线程死亡,伴随线程也会跟着一起死亡。
7,sleep(毫秒);设置线程休眠。
5,线程的生命周期:(背)
使用线程构造器·---创建线程对象---》线程新生状态
创建线程对象,start()----》进入到就绪状态(有资格,没资源)
线程对象,run()---》进入到运行状态(有资格,有资源)---在时间片段内,执行完---死亡状态
---在时间片段内,没执行完---重新回到就绪状态,继续等待
---在时间片段内,出现突发事件---阻塞状态,直到突发事件结束---回到就绪状态
6,解决线程安全问题:
【第一种:同步代码块】
synchronized (Window.class) {
if (ticket >= 1) {
System.out.println(Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
}
}
【第二种:同步方法】
public static synchronized void buyTicket(){ /*synchronized 锁子 this当前线程对象。 */
//if(ticket >= 1) {
//System.out.println(Thread.currentThread().getName() + "窗口,卖出第" + ticket + "票");
//ticket--;
// }
// }
/*
【第三种方法】
static Lock lock=new ReentrantLock();//创建lock锁对象
@Override //【lock锁】
public void run() {
while (true) {
lock.lock();//上锁
if (ticket >= 1) {
System.out.println(getName() + "窗口,卖出第" + ticket + "票");
ticket--;
}
lock.unlock();//解锁
if (ticket == 0) {
break;
}
}
}
7,线程通信:
*/
public static void main(String[] args) {
}
}
IO流代码
//Student类
package com.jr.date729.ioliu;
import java.io.Serializable;
import java.util.Objects;
//标记接口,不需要重写任何方法
public class Student implements Comparable<Student> , Serializable {
/*
属性类型以包装类型存在!
*/
private Integer stuId;
private String stuName;
private Integer age;
private String sex;
public Student() {
}
public Student(Integer stuId, String stuName, Integer age, String sex) {
this.stuId = stuId;
this.stuName = stuName;
this.age = age;
this.sex = sex;
}
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) throws Exception {
this.age = age;
throw new Exception("提醒的内容");
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(stuId, student.stuId) &&
Objects.equals(stuName, student.stuName) &&
Objects.equals(age, student.age) &&
Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(stuId, stuName, age, sex);
}
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
/*if(stuId>o.stuId){
return -1;
}else if(stuId<o.stuId){
return 1;
}else{
return 0;
}*/
return stuName.compareTo(o.stuName);
}
}
//Test类
package com.jr.date729.ioliu;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//new Test1().getFilesInfo("C\\idea");
//test3();
}
public static void test1() throws IOException {
File file = new File("C:" + File.separator + "idea" + File.separator + "ioliu.txt");
/*
扩充:
windows中分隔符是\\
linus是/
File.separator 不确定在哪里运行,可以改换成(自动获得适合于当前系统的分隔符)
*/
System.out.println(file.length());//输出文件的字节大小
System.out.println(file.canExecute());//判断系统是否可以操作该文档
System.out.println(file.canRead());//判断系统是否可以读取该文档
System.out.println(file.getName());//获取文件名
System.out.println(file.exists());//判断文件是否存在
System.out.println(file.isDirectory());//判断文件是否是目录
System.out.println(file.isFile());//判断是否是文件
System.out.println(file.length());//获得文件大小
System.out.println(file.delete());//删除文件
System.out.println(file.getParent());//获得上级目录的名字
//file.createNewFile();//会有IO流异常 判断是否存在,如果不存在就创建这个文件
System.out.println(file.exists());//判断文件是否存在
long time=file.lastModified();//获取文件的最后修改时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
System.out.println(file.getAbsolutePath());
}
public static void test2() {
//File file = new File("C:\\idea\\abc");
File file1=new File("C:\\idea\\aaa\\bbb\\ccc");
if (file1.exists()) {//判断文件是否存在
file1.delete();//只删除一层,需要循环操作,不能删除非空文件
System.out.println("删除成功");
} else {
file1.mkdirs();//mkdir()只能创建一级文件夹 mkdirs()可以创建多级文件夹
System.out.println("创建成功");
}
}
public static void test3() {
//获取当前目录下所有 一级文件名称 到一个字符串数组中去返回
File file=new File("C:\\idea");
String[] list = file.list();
for (String s : list) {
System.out.println(s);
}
//获取当前目录下所有 一级文件对象 到数组中去返回
/*
File file = new File("C:\\idea");
File[] files = file.listFiles();
System.out.println(file + "zzzz");
for (File f : files) {
System.out.println(f);
}
*/
}
public void getFilesInfo(String url) {
File file = new File(url);
File[] files = file.listFiles();
for (File f : files) {
if (f.isDirectory()) {
getFilesInfo(f.getPath());
} else {
System.out.println(f);
}
}
}
public static void test4() throws IOException {
//1,获得水源对象(获得信息的来源对象)
File file = new File("C:\\idea\\ioliu.txt");
//2,创建水管对象,获得io流对象
FileInputStream fis = new FileInputStream(file); //字节流
//3,读取信息
int i = fis.read();
while (i != -1) {
System.out.print((char) i);
i = fis.read();
}
System.out.println(fis.read());//每次只读一个字节
//4,关闭流对象资源
fis.close();
}
public static void test5() throws IOException {
//1,获得水源对象(获得信息的来源对象)
File file = new File("C:\\idea\\ioliu.txt");
//2,创建水管对象,获得io流对象
FileInputStream fis = new FileInputStream(file); //字节流
//3,读取信息
byte[] bytes = new byte[100];
int i = fis.read(bytes);//每次读取100个字节,将100个字节存储到bytes数组中
while (i != -1) {
for (byte b : bytes) { //效率低,不管元素个数有多少个,都要执行100遍
System.out.print((char) b);
}
i = fis.read();
}
System.out.println(fis.read());//每次只读一个字节
//4,关闭流对象资源
fis.close();
}
public static void test6() throws IOException {//把图片复制到另一个地方
//图片,视频,音频都用字节流来操作
//1,获得数据源对象(2个)
File inputfile = new File("C:\\tupian\\屏幕截图 2024-07-26 114606.png");
File outputFlie = new File("C:\\屏幕截图 2024-07-26 114606.png");
//2,获得流对象
FileInputStream fil = new FileInputStream(inputfile);
FileOutputStream fos = new FileOutputStream(outputFlie);
//3,读写信息:
byte[] bytes = new byte[1024];
int i = fil.read(bytes);
while (i != -1) {
fos.write(bytes);
i = fil.read(bytes);
}
//关闭流资源;后开的先关
fos.close();
fil.close();
System.out.println("图片复制完成");
}
public static void test7() throws IOException {
//图片,视频,音频都用字节流来操作
//1,获得数据源对象(2个)
File inputfile = new File("C:\\tupian\\ioliu.txt");
File outputFlie = new File("C:\\ioliu.txt");
//2,获得流对象
FileInputStream fil = new FileInputStream(inputfile);
FileOutputStream fos = new FileOutputStream(outputFlie);
//3,读写信息:
byte[] bytes = new byte[1024];
int i = fil.read(bytes);
while (i != -1) {
fos.write(bytes);
i = fil.read(bytes);
}
//关闭流资源;后开的先关
fos.close();
fil.close();
System.out.println("复制完成");
}
public static void test8() throws IOException {
//字符输入流
//1,获得数据源对象
File file = new File("C:\\tupian\\ioliu.txt");
//2,获得管道对象
FileReader fr = new FileReader(file); //获得字符输入流
//3,读取
char[] cs = new char[1024];//缓冲区
int i = fr.read(cs);//每次读取1014个字符,如果光标的后面没有内容,i=-1,如果后面还有内容,读到的是本次读到的真实的字符个数
fr.read();
while (i != -1) {
System.out.println(cs);
i = fr.read(cs);
}
//4,关闭
fr.close();
}
public static void test9() throws IOException {
//模拟微信聊天信息存储功能
//1,获得信息源对象
File file = new File("C:\\tupian\\ioliu.txt");
//2,获得流对象
FileWriter fw = new FileWriter(file, true);//末尾追加 false直接覆盖
//3,写入
Scanner input = new Scanner(System.in);
System.out.println("请输入你要存储的文字信息,输入exit退出:");
String str = input.next();
while (!"exit".equals(str)) {
fw.write(str + "\n");
System.out.println("请输入你要存储的文字信息,输入exit退出:");
str = input.next();
}
//4,关闭流对象
//fw.flush();//刷新管道
fw.close();
}
public static void test10() throws IOException {
//使用对象流,将内存对象--外部文件里---序列化
//外部文件里对象信息 读取到内存里-->反序列化
//1,获取信息源对象
File file = new File("C:\\tupian\\ioliu.txt");
//2,获得管道对象
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
//3,开始序列化
Student stu = new Student(1, "张三", 34, "男");
oos.writeObject(stu);
//4,关闭流对象//同一个方向的多层流对象,关闭最里层流对象就可以
oos.close();
System.out.println("序列化成功");
}
public static void test11() throws IOException, ClassNotFoundException {
//使用对象流,将内存对象--外部文件里---序列化
//外部文件里对象信息 读取到内存里-->反序列化
//1,获取信息源对象
File file = new File("C:\\tupian\\ioliu.txt");
//2,获得管道对象
FileInputStream fis = new FileInputStream(file);
ObjectInputStream oos = new ObjectInputStream(fis);
//3,开始反序列化
Student stu =(Student)oos.readObject();
System.out.println(stu);
//4,关闭流对象//同一个方向的多层流对象,关闭最里层流对象就可以
oos.close();
System.out.println("反序列化成功");
}
}
IO练习
//Student类
package com.jr.date729.ioliu.xiti;
import java.io.Serializable;
public class Student implements Comparable<Student>, Serializable {
private static final long serialVersionUID = -323316069108636610L;
private Integer id;
private String name;
private Integer age;
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return age.compareTo(o.age);
}
}
//Test类
package com.jr.date729.ioliu.xiti;
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
new Test().main1();
new Test().main2();
}
public void main1() throws IOException {
//1.获得信息源对象
File file = new File("C:\\idea\\ioliu.txt");
//2.获得管道对象:
FileOutputStream fos = new FileOutputStream(file);//节点流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//3.写入:
oos.writeObject(new Student("张三1", 23));
oos.writeObject(new Student("张三2", 24));
oos.writeObject(new Student("张三3", 25));
//4.关闭流对象资源
oos.close();
}
public void main2() throws IOException, ClassNotFoundException {
//1.获得信息源对象
File file = new File("C:\\idea\\ioliu.txt");
//2.获得管道对象:
FileInputStream fis = new FileInputStream(file);//节点流
ObjectInputStream ois = new ObjectInputStream(fis);
//3.写入:
System.out.println((Student) ois.readObject());
System.out.println((Student) ois.readObject());
System.out.println((Student) ois.readObject());
//4.关闭流对象资源
ois.close();
}
}
线程同步的方法
package com.jr.date729.thread.chuangjianxianchengfangshi2;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Window implements Runnable {
static int ticket = 500;
//第一种同步代码块
/*
@Override
public void run() {
while (true) {
synchronized (Window.class) {
if (ticket >= 1) {
System.out.println(Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
}
}
if (ticket == 0) {
break;
}
}
}
*/
//第二种同步方法
/*
@Override
public void run() {
while (true) {
if (ticket == 0) {
break;
}
buyTicket();
}
}
public static synchronized void buyTicket() {//synchronized 锁子this当前线程对象
if (ticket >= 1) {
System.out.println(Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
}
}
*/
//第三种方式:lock锁
Lock lock = new ReentrantLock();//创建lock锁对象
@Override
public void run() {
while (true) {
lock.lock();//上锁
if (ticket >= 1) {
System.out.println(Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
}
lock.unlock();//开锁
if (ticket == 0) {
break;
}
}
}
}
//Test类
package com.jr.date729.thread.chuangjianxianchengfangshi2;
public class Test {
public static void main(String[] args) {
Window w1 = new Window();
Thread t1 = new Thread(w1, "第一");
t1.start();
Thread t2 = new Thread(w1, "第二");
//t2.setPriority(2);//设置线程的优先级别1-10之间,默认是5
t2.start();
Thread t3 = new Thread(w1, "第三");
t3.start();
}
}