java: ----- 多线程、IO流、字符流(Buffered缓冲加强版)Copy
多线程
进程:正在运行的程序.
线程:每一个进程中都会有多个任务,每个任务就是一个线程.
单线程:程序中只有一个任务,只有一条执行路径.
多线程:程序中有多个任务,有多条执行路径.
- 注意:进程想要执行必须抢到cpu的执行权.进程中如果线程较多抢到cpu的概率就会比较高.
但是不保证一定能抢到,因为cpu的执行是随机性的.
并行:在某一个时间点上同时执行多个.
并发:在某一个时间点上只能执行一个.
多线程的实现方式
方式1:继承Thread ***
- 1.创建自定义类继承Thread
- 2.覆盖run方法
- 3.创建对象
- 4.启动线程 start()
方式2:实现Runnable接口 ***
- 1.自定义类实现Runnable
- 2.覆盖run方法
- 3.创建对象
- 4.创建Thread对象将第3步作为参数
- 5.启动线程
第二种方式好一些,避免了java单继承带来的局限性.
Thread中的方法:
- String getName():返回此线程的名称 ***
- void setName(String name):设置线程名称 ***
- static Thread currentThread():返回对当前正在执行的线程对象 ***
- int getPriority():返回此线程的优先级
- void setPriority(int newPriority):更改此线程的优先级
- static void sleep(long millis):睡眠 ***
- void join():等待这个线程死亡 *** t.join 只用t线程执行完毕后 才会执行当前线程
堆空间:
多进程之间的堆空间是相互独立的,多线程之间共用一个堆空间。例如两个线程创建的对象放在一个堆空间当中。
栈空间:
每一个线程都有独立的栈空间,用来存储局部变量,每当启动一个线程虚拟机就会为它创建一个新的栈空间。
线程安全问题
线程不安全:
- 多个线程操作同一个对象(临界资源),破坏了不可分割的操作(原子性操作),就会产生数据不安全问题.
如何解决?
- 多个线程访问临界资源,保证原子性操作不被破坏所以需要同步(线程安全|同步).这是一个整体代码,要么不执行,如果执行必须保证其他线程无法操作这段代码.java
为这种思想提供了技术:同步代码块
synchronized (对象(锁标记)) {
原子性操作
}
- 只有拿到锁标记的线程才能进入同步代码块
- 同步方法: 将synchronized关键字定义在方法上,同步方法的锁对象是: this
死锁
- :两个或者多个线程之间产生了相互等待的情况.
- 如何解决死锁 – 等待唤醒机制
- void wait():当前线程处于无限期等待. 该方法必须在同步代码块中才能使用.调用后会释放该线程拥有的所有锁标记.调用wait会使当前线程进入到当前锁对象的等待队列.
例如: t1线程 、o.wait 、 o对象的等待队列为【t1,t2】并且是去锁标记
- void notify() | notifyAll() : 释放锁对象上等待的单个线程(上例中t1)|多个线程(上例中t1、t2).该方法必须在同步代码块中才能使用. 注 :以上两个方法必须是锁对象调用.
例如 o.notify() | o.notifyAll():
释放锁对象上等待的单个线程(上例中t1)|多个线程
IO流
数据方向:输入流、输出流(读、写)
数据单位:字节流、字符流
流的功能:节点流、过滤流(节点流是完成数据的读写、过滤流:为其他流增加功能)
字节流
- 字节输入流 InputStream(abstract) 父类
- 字节输出流 OutputStream(abstract) 父类
- 字符输入流 Reader(abstract)
- 字符输出流 Writer(abstract)
FileInPutStream/FileOutPutStream文件字节流 节点流
字节流写
案例:
//字节流写 给个文件名
FileOutputStream fileOutputStream = new FileOutputStream("D:\\giveFileName.txt");
fileOutputStream.write('A');
fileOutputStream.close();
如果文件已经存在 则覆盖
要想覆盖或者在末尾追加 则代码如下
//字节流写 给个文件名 第二个参数表示是否要追加
FileOutputStream fileOutputStream = new FileOutputStream("D:\\giveFileName.txt",true);
fileOutputStream.write('A');
fileOutputStream.close();
字节流写方法
- void write(int b):只写单个字节 ***
- void write(byte[] b):写一个字节数组 ***
- void write(byte[] b, int index, int len):写字节数组的一部分 ***
package io;
import java.io.*;
public class FileOutPutStream {
public static void main(String[] args) throws Exception {
//字节流写 给个文件名 第二个参数表示在原文件后追加
FileOutputStream fileOutputStream = new FileOutputStream("D:\\giveFileName.txt",true);
String string="ABCDEFGHIZKLMNOPQRSTUVWXYZ";
byte[] bytes = string.getBytes();
fileOutputStream.write(bytes);
fileOutputStream.close();
}
}
FileOutputStream fileOutputStream = new FileOutputStream("D:\\giveFileName.txt",true);
String string="abcdefg";
byte[] bytes = string.getBytes();
fileOutputStream.write(bytes,2,4);
fileOutputStream.close();
异常try/catch处理方法
package io;
import java.io.*;
public class FileOutPutStream {
public static void main(String[] args){
//字节流写 给个文件名 第二个参数表示在原文件后追加
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("D:\\giveFileName.txt",true);
String string="ABCDEFG";
byte[] bytes = string.getBytes();
fileOutputStream.write(bytes,2,4);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
写换行等
如何实现数据的换行写入? * windows: \r\n * linux: \n * mac: \r
字节流读
FileInputStream
案例:
package io;
public class FileInputStream {
public static void main(String[] args) throws Exception {
java.io.FileInputStream fileInputStream = new java.io.FileInputStream("D:\\giveFileName.txt");
while (true) {
int read = fileInputStream.read();
if (read==-1)break;
System.out.print((char) read);
}
fileInputStream.close();
}
}
高效率读取
package io;
public class FileInputStream {
public static void main(String[] args) throws Exception {
java.io.FileInputStream fileInputStream = new java.io.FileInputStream("D:\\giveFileName.txt");
byte[] bytes = new byte[1024];
while (true) {
int read = fileInputStream.read(bytes);
if (read==-1)break;
for (int i = 0; i < read; i++) {
System.out.print((char) bytes[i]+"\t");
}
}
fileInputStream.close();
}
}
字节流实现文件copy
package io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileInAndOutCopy {
public static void main(String[] args) {
copy("D:\\giveFileName.txt", "D:\\newGiveFileName.txt");
}
static void copy(String oldName, String newName) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(oldName);
fileOutputStream = new FileOutputStream(newName);
byte[] bytes = new byte[1024];
while (true) {
int read = fileInputStream.read(bytes);
if (read == -1) break;
fileOutputStream.write(bytes, 0, read);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null && fileOutputStream != null) {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
过滤流
DataInputStream/DataOutputStream
- 读写八种基本类型和字符串
缓冲流(Buffered文件Copy)
- 提高IO效率,减少访问磁盘的次数
package io;
import java.io.*;
import java.io.FileInputStream;
public class BufferedCopy {
public static void main(String[] args) {
copy("D:\\giveFileName.txt", "D:\\newGiveFileName.txt");
}
static void copy(String oldName, String newName) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
FileInputStream fileInputStream = new FileInputStream(oldName);
bufferedInputStream = new BufferedInputStream(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(newName);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] bytes = new byte[1024];
while (true) {
int read = bufferedInputStream.read(bytes);
if (read == -1) break;
bufferedOutputStream.write(bytes, 0, read);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedInputStream != null && bufferedOutputStream != null) {
try {
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流
- Reader和Writer(字符流的父类 抽象类)
- FileReader和FileWriter(文件字符流)
- BufferedReader和BufferedWriter 缓冲流 提高IO效率 减少访问磁盘次数
为什么使用字符流?
- 因为字节流在读取数据时每次读取1字节,而中文占用2字节空间,每次只能读取一个中文的一半.
Writer类中写数据的方法:
- void write(int c):写一个字符
- void write(char[] cbuf):写入一个字符数组.
- void write(char[] cbuf, int off, int len):写字符数组的一部分
- void write(String str):写入一个字符串 ***
- void write(String str, int off, int len):写字符串的一部分
字符流读数据的方法:
- int read():读一个字符 ***
- int read(char[] cbuf):读一个字符数组 ***
flush()和close()的区别?***
- flush:刷新
- close:先刷新,再关流
字符流copy
package io;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestReadWrite {
public static void main(String[] args) throws IOException {
FileWriter fileWriter = new FileWriter("D:\\fileWrite.txt",true);
fileWriter.write("今天是2020年7月9日\r\n");
fileWriter.write("天气小雨\n");
fileWriter.write("上午去西土城面试了\n");
fileWriter.write("下午寝室面试了\n");
fileWriter.write("一天又过去了哈哈真开心\n");
fileWriter.close();
FileReader fileReader = new FileReader("D:\\fileWrite.txt");
char[] chars = new char[1024];
while (true){
int read = fileReader.read(chars);
if (read==-1)break;
for (int i = 0; i < read; i++) {
System.out.print((char)chars[i]);
}
}
fileReader.close();
}
}
buffered加强的缓冲字符流拷贝
代码
package io;
import java.io.*;
public class BufferedReadWrite {
public static void main(String[] args) throws IOException {
FileWriter fileWriter = new FileWriter("D:\\fileWrite.txt",true);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.println("今天是2020年7月9日");
printWriter.println("天气小雨");
printWriter.println("上午去西土城面试了");
printWriter.println("下午寝室面试了");
printWriter.println("一天又过去了哈哈真开心");
printWriter.close();
FileReader fileReader = new FileReader("D:\\fileWrite.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
while (true){
String line = bufferedReader.readLine();
if (line==null)break;
System.out.println("line = " + line);
}
fileReader.close();
}
}
结果
上一篇: JAVA基础复习二十-IO流-字节流
下一篇: Java 字符串连接的性能问题分析