目录
文件与流
文件管理
针对文件或是目录路径名的管理,包括文件的属性信息、检查,、删除等,但不包括文件的访问
File类
对文件系统中的文件和目录进行操作,一个File对象可以代表一个文件,也可以代表一个目录。
- 构造方法
- File path=new File("c:\\");
File file1=new File("c:\\sss.txt"); - File file2=new File("c:\\","sss.txt");
- File file3=new File(path,"sss.txt");
- File path=new File("c:\\");
- 注意:
-
调用File类方法时必须使用try…catch语句块
-
-
常用方法
-
创建和删除
-
boolean mkdir() //创建一个新目录,不包括子目录
-
boolean mkdirs() //创建目录及子目录,即一次可以创建多级目录
-
boolean createNewFile() //创建一个新的空文件
-
boolean delete() //删除一个空目录或文件
-
boolean renameTo(File) // 目录或文件改名
-
-
文件属性测试
-
canRead() //可读否
-
canWrite() //可写否
-
exists() //File对象存在吗
-
isDirectory() //是目录吗
-
isFile() //是文件吗
-
isAbsolute() //有File(parent, filename)构建器创建对象时给出的是绝对路径吗
-
isHidden() //是隐含文件吗
-
SetReadOnly() //设置为只读文件吗
-
getName() //不含路径的文件名
-
getPath() //路径文件名
-
getParent() //父目录名
-
getAbsolute() //返回绝对路径
-
toString() //返回File对象的信息
-
long length() //返回文件长度(字节数)
-
long lastModified() //返回文件的最后修改时间
-
int compareTo(File f) //比较两个File对象,而不是比较文件内容
-
boolean equals(Object o) //自Object类继承而来的方法
-
-
显示目录清单
-
File[] files = path.listFiles();
// 循环打印各文件情况 用for循环
for (File f : files) {
// 可以通过get方法获取一些属性
System.out.println(f.getName());
}
-
-
流的概念及API
流
- 概念:程序中数据的流通,数据流是一串连续不断的数据的集合。
- 分类:
- 按流的方向不同分为:输入流、输出流
- 按处理数据的单位不同分为:字节流、字符流
- 按功能不同分为:节点流、处理流
- 输入流InputStream常用方法
方法 | 含义 |
int read() | 一次读取一个byte的数据,并以int类型把数据返回来,如果没有数据可以读了,会返回”-1” |
int read(byte[] buffer) | 把所读取到的数据放在这个byte数组中,返回一个int型的数据,这个int型数据存储了返回的真正读取到的数据byte数 |
int read(byte[] buffer,int offset,int length) | 读取length个字节,并存储到一个字节数组buffer中,并从offset位置开始返回实际读取的字节数 |
void close() | 关闭此输入流并释放与该流关联的所有系统资源 |
4. 输出流OutputStream常用方法
方法 | 含义 |
void write(byte[] buffer) | 将要输出的数组先放在一个byte数组中,然后用这个方法一次把一组数据输出出去 |
void write(byte[] buffer,int off,int len) | 将指定字节数组中从偏移量off 开始的 len 个字节写入此输出流 |
abstract void write(int b) | 将指定的字节写入此输出流 |
void close() | 关闭此输出流并释放与此流有关的所有系统资源 |
void flush() | 刷新此输出流并强制输出所有缓冲的输出字节 |
字符流
- 注意:存文件时要用utf-8编码,否则与我们的工作区编码方式 不匹配,出现乱码
- 应用:
- 读取文件内容:BufferedReader br = new BufferedReader(fr); String str = br.readLine(); 如果没有可读取行,返回null
- 写字符流文件: fileWriter = new FileWriter(file,true); bw=new BufferedWriter(fileWriter);
bw.write( str)
对象的序列化和反序列化
序列化:对文件的写入对象的操作
-
对象序列化涉及的流
节点流:FileOutputStream FileInputStream
处理流:ObjectOutputStream ObjectInputStream -
把对象写入到--->txt文件里,用到的是FileOutputStream ObjectOutputStream
ObjectOutputStream.writeObject(Object o) -
样例代码
public class Test{
@Test
public void test01() throws IOException{
//ObjectOutputStream writeObject(Object obj)
//为ObjectOutputStream准备一个节点流 FileOutputStream
FileOutputStream fos=null;
//step1 实例化一个工具ObjectOutputStream
ObjectOutputStream oos=null;
try {
System.out.println("开始实例化输出流对象");
File file=new File("d:/java24/dept01.txt");
fos=new FileOutputStream(file);
oos=new ObjectOutputStream(fos);
System.out.println("实例化输出流对象结束");
//--把dept对象存到dept01.txt
//step 2 准备一个dept01对象
System.out.println("准备一个dept对象");
Dept dept10=new Dept();
dept10.setDeptNo(10);
dept10.setDname("部门10");
dept10.setLoc("沈阳");
//step 3把对象持久化到文件里
if(dept10!=null){
System.out.println("开始序列化对象");
oos.writeObject(dept10);
System.out.println("序列化对象结束");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
oos.close();
}
}
}
对象的反序列化:序列化的反过程,从文件中将对象读取出来
样例代码
public class Test{
@Test
public void test02() throws IOException{
FileInputStream fis=null;
//step1 实例化一个工具ObjectInputStream
ObjectInputStream ois=null;
try {
System.out.println("开始准备工具类");
File file=new File("d:/java24/dept01.txt");
fis=new FileInputStream(file);
ois=new ObjectInputStream(fis);
System.out.println("开始反序列化对象");
Dept dept=(Dept) ois.readObject();
if(dept!=null){
System.out.println(dept.getDname());
}
} catch (Exception e) {
// TODO: handle exception
}finally{
ois.close();
}
}
}
多线程
进程与线程
-
进程Process: 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。可以把进程简单理解为操作系统中运行的一个程序
-
线程Thread:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
-
多线程是指在同一程序中有多个顺序流在执行。进程是线程的容器,一个进程里可以运行1-N个线程,操作系统以进程为单位分配资源
实现线程的方式
class ThreadTest extends Thread{
public void run(){
System.out.println("这个线程开始运行");
}
}
public class Test {
public static void main(String[] args) {
ThreadTest tt = new ThreadTest ();
tt.start(); //启动一个线程
}
}
2. 实现Runnable接口
class ThreadTest implements Runnable{
public void run(){
System.out.println("这个线程开始运行");
}
}
public class Test {
public static void main(String[] args) {
ThreadTest tt = new ThreadTest ();
Thread t = new Thread(tt);
t.start(); //通过一个线程对象启动它
}
}
继承Thread类和实现Runnable接口的区别:
继承Thread类:编写简单,可直接操作线程。适用于单继承
实现Runnable接口:避免单继承局限性,便于共享资源,需要重写run()方法
3.实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
//创建Callable接口实现类,并实现call()方法,此方法为线程执行体,且有返回值
class CallableThreadTest implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("执行线程");
return 1;
}
}
public class Test {
public static void main(String[] args) {
//使用FutureTask类(实现了Future和Runnable接口)来包装Callable对象
FutureTask<Integer> ft = new FutureTask<>(new CallableThreadTest());
//使用FutureTask对象作为Thread对象的target创建并启动新线程
new Thread(ft).start();
//调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
try {
System.out.println("子线程的返回值:" + ft.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Runnable和Callable的区别:
- Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
- call方法可以抛出异常,run方法不可以。
- 运行Callable任务可以拿到一个Future对象。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
线程的生命周期
新建、就绪、阻塞、等待、终止
线程调度常用方法
方法 | 功能 |
getName() setName() | 设置或获取当前线程名称 |
isAlive() | 判断线程是否存活(就绪、运行、阻塞是存活状态) |
getPriority() | 获取线程优先级 |
setPriority() | 设置线程优先级 |
Thread.sleep() | 强迫线程睡眠(单位:毫秒)(不释放同步锁) |
join() | 等待某线程结束,再恢复当前线程的运行 |
yield() | 让出CPU资源,当前线程进入就绪状态 |
wait() | 当前线程进入等待状态,即进入等待池。(释放同步锁,由notify()唤醒) |
notify() notifyAll() | 唤醒等待池中的某个或全部等待线程 |
线程的中断
- 分类:
-
自动终断【完成】:一个线程完成执行后(即run方法执行完毕),不能再次运行
-
手动中断:
stop( ) —— 已过时,基本不用。(不安全,就像是突然停电)
interrupt( ) ——此方法只是改变中断状态,不会中断一个正在运行的线程。比如:如果当前线程是阻塞状态,那么就结束阻塞状态
-
可通过使用一个标志指示 run 方法退出,从而终止线程
-
线程同步解决方案
synchronized:同步锁(互斥锁)
- 特点:
-
.在java语言中,引入了同步锁的概念,每个对象都有一个与之关联的内部锁(排他锁),用以保证共享数据的安全性问题。
-
关键词synchronized用来给某个方法或某段代码加上一个同步锁。
-
当调用者调用此方法时,必须获得这把锁才可以调用。
-
当某个调用者获得这把锁之后,其他调用者就无法获得了。
-
当调用结束后,调用者释放这把锁,此时其他调用者才可以获得。
-
这个机制保障了某个同步方法同时只能有一个调用者
-
-
使用方法:
-
锁定方法:
public class Account { private int balance = 1000; public synchronized void qu(){ // 同步方法 if(balance>=1000){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } balance -= 1000; System.out.println("取了1000元,balance = " + balance); } } }
-