一.线程补充内容
达到线程同步的条件的步骤
1.确认谁是共享数据,synchronized要锁住谁
2.锁住谁就执行谁的wait()和notify()
3.提供boolean的旗标,来判断什么时候开始等待,什么时候不需要等待
锁的释放问题
什么时候锁会释放
1.临界区代码执行完毕(使用notify不会立即释放锁,也会等待临界区代码执行完毕)
2.临界区代码执行过程中遇到error或者exception
3.临界区代码执行过程中出现return,break
4.调用wait方法,立即释放锁
什么时候锁不释放
sleep
yeild
二.I/O流
数据流向
以程序作为媒介
把程序得到的数据发送到某些位置上(控制台,文件,网络)
可以把外部(网络,文件)的数据传输到程序中
流的分类
1.根据数据的流向
输入流和输出流
2.根据数据的类型
字节流和字符流
java中流是什么
流就是一个对象
JDK种提供了很多流的类
一些类是以InputStream和OutputStream结尾的
一些类是以Writer和Reader结尾的
字节输入流(InputStream),字节输出流(OutputStream)
字符输入流(Reader),字符输出流(Writer)
一些实例
1.InputStream,OutputStream
输入流提供了读的方法
read();//一个字节一个字节读
read(byte[] b);
read(byte[] b , int off , int len)//
输出流提供了写的方法
write(int i);//写出对应的字节
write(byte[] b);//写出对应的字节数组
write(byte[] b, int off , int len);//
2.FileInputStream,FileOutputStream
文件流,字节流
总结了一下使用流的步骤
1.根据业务逻辑确定要使用什么流
2.选择好流之后对流进行初始化
3.使用读取方法read和写入方法write进行操作
4.使用完毕之后记得手动关闭流的资源
实例:用流实现文件的拷贝
/**
* 使用流进行文件拷贝 从在桌面上拷贝一个文件到工作空间中
*
* @author Acer
*
*/
public class FileCopy {
public static void main(String[] args) {
// 第一步,选择使用那个流
FileInputStream fis = null;// 输入流
FileOutputStream fos = null;// 输出流
// 对流进行初始化
try {
//传递要读取的文件位置
fis = new FileInputStream("C:/Users/Acer/Desktop/01.jpg");
//传递文件输出的位置
fos = new FileOutputStream("D:/copy.jpg");
//第三步:读取文件
System.out.println("文件开始读取");
int len = 0;
//定义一个字节数组的缓冲区
byte[] b = new byte[1024];
while((len = fis.read(b))!=-1) {
//当len=-1的时候,代表文件到达末尾,跳出循环
//当i!=-1的时候证明读到了字节,需要写出去
// System.out.println(new String(b));
// fos.write(len);
fos.write(b);
}
System.out.println("文件输出完毕");
//第四步:使用完流之后记得关闭资源
//记住开几个关几个,可以使用finally代码块
fos.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(fos!=null) fos.close();
if(fis!=null) fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
因为要多次执行资源关闭的操作,所以对资源关闭进行了封装,后面的测试都直接使用了封装的方法.
/**
* 封装一下关闭资源的方法
* 成对的关闭字节输入流和字节输出流 in 字节输入流 out 字节输出流
* @author Acer
*
*/
public class CloseUtil {
public static void closeStream(InputStream in, OutputStream out) {
try {
if (in != null)
in.close();
if (out != null)
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.BufferedInputStream,BufferedOutputStream
缓冲流,字节流,包装流
主要用来提升效率的
注意谁是基础流,谁是包装流
read(byte[]);读取一个byte数组
write(byte[],off,len)这个len是实际读到的字节数
没有必要把byte数组的长度全部读出来,会造成多读
缓冲流相关测试:
/**
* 缓冲流测试
*
* @author Acer
*
*/
public class BufferTest {
public static void main(String[] args) {
// 1.先确认要使用什么流
// 需要使用包装流,需要使用对应的文件流
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
FileInputStream fis = null;
FileOutputStream fos = null;
// 对四个流进行初始化
// 需要读取的文件名字
try {
String inPath = "8.3.txt";// 必须是桌面有的文件,而且必须带后缀
fis = new FileInputStream(new File(UrlFiled.DESKTOP + inPath));
// 需要写入的文件名字,如果文件不存在,则自动创建
String outPath = "new.txt";
fos = new FileOutputStream(new File(UrlFiled.PROJECT + outPath));
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
// 读取资源并写出
byte[] b = new byte[8];
int len = -1;
while ((len = bis.read(b)) != -1) {
System.out.println(len);
bos.write(b, 0, len);
bos.flush();// 清空一下缓冲区
}
System.out.println("资源写出完毕...");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//关闭资源,使用封装的方法
CloseUtil.closeStream(bis, bos);
CloseUtil.closeStream(fis, fos);
}
}
}
4.DataInputStream,DataOutputStream
字节流,包装流,数据流
读写java中的基本数据类型的
一般不会直接从文件中读取
作为一个数据的持久化来做的,一般做法,把基本数据类型保存到文件中作为
持久化的一个方式,然后等到需要的时候再从文件中取出来
测试基本数据类型的存取:
/**
* 测试基本数据类型的存取
*
* @author Acer
*
*/
public class DataTest {
public static void main(String[] args) {
DataInputStream dis = null;
DataOutputStream dos = null;
FileInputStream fis = null;
FileOutputStream fos = null;
// 先写入
try {
// fos = new FileOutputStream(UrlFiled.PROJECT+"data.txt");
// //
// dos = new DataOutputStream(fos);
// System.out.println("开始输入数据");
// //不需要使用循环写入,直接写
// dos.writeInt(20);//写入文件一个int类型的数据
// dos.writeLong(30L);//写入文件一个long类型的数据
// dos.writeBoolean(true);
// dos.writeDouble(10.0);
// dos.writeChar(97);
// dos.writeFloat(40.0f);
// System.out.println("输出数据完毕,请查看指定位置...");
// 开始读取曾经保存的数据类型
fis = new FileInputStream(UrlFiled.PROJECT + "data.txt");
dis = new DataInputStream(fis);
// 直接开始读
System.out.println("开始读取数据");// 读取时必须按写入的顺序来进行读取
System.out.println("读取到的int数据" + dis.readInt());
System.out.println("读取到的long数据" + dis.readLong());
System.out.println("读取到的boolean数据" + dis.readBoolean());
System.out.println("读取到的double数据" + dis.readDouble());
System.out.println("读取到的char数据" + dis.readChar());
System.out.println("读取到的float数据" + dis.readFloat());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
CloseUtil.closeStream(dis, dos);
CloseUtil.closeStream(fis, fos);
}
}
}
5.ObjectInputStream,ObjectOutputStream
字节流
读写对象类型的数据
向文件中写入一个对象保存
从文件中读出一个对象保存
保存对象测试:
/**
* 测试保存一个对象到文件里 以字节的形式保存一个对象
*
* @author Acer
*
*/
public class ObjectTest {
public static void main(String[] args) {
ObjectOutputStream oos = null;
FileOutputStream fos =null;
try {
File objectfile = new File(UrlFiled.PROJECT+"obj");
fos = new FileOutputStream(objectfile);
oos = new ObjectOutputStream(fos);
//往文件中写入一个对象
Student stu = new Student("tom", 22, "男");
// oos.writeObject("今天中午该吃饭了");//String实现过序列化
System.out.println("开始写入对象");
oos.writeObject(stu);
System.out.println("写入对象成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
CloseUtil.closeStream(null, oos);
CloseUtil.closeStream(null, fos);
}
}
}
序列化和反序列化
序列化:该对象具有能够变成字节的权利,可以通过字节流保存到文件里
反序列化:可以从文件中读取并且通过字节序列构建成一个对象
如何让对象实现序列化
java.io.Serializable 接口
让该对象的类实现序列化接口
三.心得
今天学的内容主要是关于i/o的api,以及对一些方法的应用,都不是很难的东西,重要的还是多写代码,明天加油!