IO流与多线程

IO流与多线程


一、IO流的分类
1.按流向不同:输入流、输出流(以程序为主体)
2.按数据不同:字节流、字符流(字节流操作非文本文件  .jpg  .avi  .rmvb  .mp3     字符流操作文本本件  .txt   .java)
3.按角色不同:节点流、处理流


二、IO流的结构体系
抽象基类                节点流                    缓冲流(处理流的一种)
InputStream            FileInputStream            BufferedInputStream
OutputStream            FileOutputStream            BufferedOutputStream(flush() - 用于清空缓冲区)
Reader                FileReader                BufferedReader  (readLine())
Writer                FileWriter                    BufferedWriter  (newLine() )



//使用缓冲流完成文件的复制
public static void copyFile(String src, String dest){
    //2. 创建缓冲流对象(BufferedInputStream),包装现有节点流
    BufferedInputStream bis = null;
    //4. 创建缓冲流对象(BufferedOutputStream), 包装现有节点流
    BufferedOutputStream bos = null;
    try {
        //1. 创建 FileInputStream 对象,同时打开指定文件
        FileInputStream fis = new FileInputStream(src);

        bis = new BufferedInputStream(fis);

        //3. 创建  FileOutputStream 对象,同时打开指定文件
        FileOutputStream fos = new FileOutputStream(dest);

        bos = new BufferedOutputStream(fos);

        //5. 使用缓冲流读取指定文件的内容
        byte[] b = new byte[1024];
        int len = 0;
        while((len = bis.read(b)) != -1){
            //6. 使用缓冲流将读取的内容写到目标文件
            bos.write(b, 0, len);
        }
//            bos.flush(); //用于强制清空缓冲区
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //7. 关闭流
        if(bos != null){
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if(bis != null){
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}


三、对象流:   ObjectInputStream  &  ObjectOutputStream
序列化:将内存中的对象永久的以二进制形式保存到磁盘中
①创建节点流对象
②使用缓冲流包装节点流(可选的)
③使用对象流包装缓冲流对象
④进行序列化操作
⑤关闭流
⑥需要序列化对象所属的类需要实现 java.io.Serializable 接口
⑦提供一个序列号  private static final long serialVersionUID = 1234256L;

注意:static 和 transient 修饰的属性不能被序列化

// 对象的序列化
    @Test
    public void test3() {
        Person p1 = new Person("张三", 18, new Computer(), "唐朝");
        Person p2 = new Person("李四", 28, new Computer(), "唐朝");
        Person p3 = new Person("王五", 25, new Computer(), "唐朝");

        ObjectOutputStream oos = null;
        try {
            FileOutputStream fos = new FileOutputStream("person.dat");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            oos = new ObjectOutputStream(bos);

            oos.writeObject(p1);
            oos.writeObject(p2);
            oos.writeObject(p3);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }   

反序列化:将磁盘中的对象读取

//对象的反序列化
    @Test
    public void test4() {
        ObjectInputStream ois = null;
        try {
            FileInputStream fis = new FileInputStream("person.dat");
            BufferedInputStream bis = new BufferedInputStream(fis);
            ois = new ObjectInputStream(bis);

            Person p1 = (Person) ois.readObject();
            Person p2 = (Person) ois.readObject();
            Person p3 = (Person) ois.readObject();

            System.out.println(p1);
            System.out.println(p2);
            System.out.println(p3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

四、控制台IO :
System.in : “标准”的输入流
System.out : “标准”的输出流 ---- 通过 System 类中 setOut() 方法可以改变 println() 的默认输出位置
System.err : “标准”的错误输出流

打印流 : PrintStream &  PrintWriter

五、转换流: InputStreamReader  &  OutputStreamWriter

    @Test
    public void test1(){
        BufferedReader br = null;
        try {
            InputStream in = System.in;
            InputStreamReader isr = new InputStreamReader(in);
            br = new BufferedReader(isr);

            String str = null;
            while((str = br.readLine()) != null){
                System.out.println("--" + str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }


七、其他IO流
数据流: DataInputStream & DataOutputStream
随即存取文件流: RandomAccessFile
    >seek(long l)
    >getFilePointer();       

八、java.io.File 类 : 用于表示文件/目录。可用于新建、删除、重命名等基本功能的操作
                但是若需要操作文件的内容,File 就无能为力,需要使用IO流
                通常File对象与IO流配合使用

访问文件名:
getName()
getPath()
getAbsoluteFile()
getAbsolutePath()
getParent()
renameTo(File newName)

文件检测
exists()
canWrite()
canRead()
isFile()
isDirectory()

获取常规文件信息
lastModified()
length()

文件操作相关
createNewFile()
delete()

目录操作相关
mkDir()
mkDirs()
list()
listFiles()




一、多线程
什么是程序?   为了完成某项特定的任务,使用某种语言,编写一组指令的集合。
什么是进程?   一个正在进行中的程序。
什么是线程?   在一个进程中执行的一套功能流程,称为线程
               在一个进程中执行的多套功能流程,称为多线程


二、为什么使用多线程?

抢占式策略系统: 系统会分配给每个执行任务的线程一个很小的时间段,当该时间段用完后
               系统会剥夺其使用权,交给其他线程去执行

1. 多线程可以提高程序的效率,可以尽可能的利用cpu的资源
2. 增强用户体验


三、如何使用多线程?

创建执行线程的方式一:
①创建一个类继承 Thread 类
②重写 run() 方法,同时编写线程执行体
③创建该子类的实例
④调用 start() 方法,启动线程。默认执行 run() 方法


创建执行线程的方式二:
①创建一个类实现 Runnable 接口
②实现接口中的 run() 方法,同时编写线程执行体
③创建该实现类的实例
④创建 Thread 实例,将实现类的实例作为参数,传递给Thread的构造器
⑤调用 Thread 类的 start() 方法,启动线程。默认执行 run() 方法


继承方式与实现方式的区别?
①当需要多个线程访问共享数据时,首选使用实现 Runnable 接口的方式
②实现 Runnable 接口,解决了Java中单继承的局限性

四、线程的常用方法
currentThread() : 获取当前线程
getName() : 获取线程名称
setName() : 设置线程名称
start() : 启动线程
sleep(long millis) : 是一个静态方法,使当前线程进入睡眠状态
join() / join(long millis) : 是一个实例方法, 使当前线程进入阻塞状态
interrupt() : 用于唤醒阻塞状态的线程
yield() : 线程让步
isAlive() : 判断线程是否处于存活状态

五、线程的优先级(1-10):默认的优先级为 5。 优先级高并不意味着线程一定先执行, 只不过更多的获取cpu的资源

MAX_PRIORITY : 10
NORM_PRIORITY : 5
MIN_PRIORITY : 1

getPriority() : 获取线程的优先级
setPriority() : 设置线程的优先级

六、线程的生命周期

七、线程同步:
模拟售票程序:实现三个窗口同时售票100张

问题: 当三个线程同时访问共享数据时,出现了 无序、重复、超额售票等多线程安全问题

解决办法:将多个线程需要访问的共享数据包装起来,确保一次只能有一个线程执行流访问该共享数据


Java为上述问题也提供了相应的解决办法


1. 同步代码块:

synchronized(同步监视器){
    //需要访问的共享数据
}

同步监视器:俗称“锁”,可以使用任意对象充当。但是确保多个线程持有同一把锁(同一个对象)

2. 同步方法:使用在方法的声明处,加 synchronized 关键字

    如:
        public synchronized void show(){ }

3. 同步锁: Lock 接口
    注意:必须保证手动的释放锁   (unlock())

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shujuboke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值