NIO提升性能
在JAVA的标准I/O中,提供了基于流的I/O实现,即InputStream和OutputStream。这种基于流的实现以字节为单位处理数据。NIO是New I/O的简称,表示一套新的JAVA I/O标准。在Jdk 1.4中开始引入,它具有以下特性:
-
为所有的原始类型提供(Buffer)缓存支持;
-
使用Java.nio.charset.Charset作为字符集编码解码解决方案;
-
增加通道(Cahnnel)对象,作为新的原始I/O抽象;
-
支持锁和内存映射文件的文件访问接口;
-
提供了基于Selector的异步网络I/O。
与流式的I/O不容,NIO是基于块(Block)的,它以块为基本单位处理数据。在NIO中,最为重要的2个组件是缓冲Buffer和通道Channel。缓冲是一块连续的内存块,是NIO读写数据的中转地。通道表示缓冲数据的源头或者目的地,它用于向缓冲读取或者写入数据,是访问缓冲的接口。
在这里插入图片描述
多线程读写同一个文件有哪些场景需要同步处理?
-
有线程正在读文件,另开辟线程写文件;
-
有线程正在写文件,另开辟线程读文件;
-
有线程正在写文件,另开辟线程写文件
总之,读写互斥,写读互斥,写写互斥,只有读读相容(可以异步)。
使用对文件加锁的方式做到线程安全
FileInputStream、FileOutputStream、RandomAccessFile均可得到FileChannel对象,对文件锁进行操作。
独占锁tryLock()
FileChannel的tryLock()是非阻塞的,也就是说,在发现文件被锁住的时候,直接返回null,并且抛出异常,如果没有锁住,直接返回该文件的文件锁。
它是独占锁,就是只能被一个线程持有,它能禁止其他线程获取共享锁,可用于写文件。
while (true) {
try {
fileLock = fileChannel.tryLock();//独占锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
共享锁tryLock(0, Long.MAX_VALUE, true)
FileChannel的tryLock(0, Long.MAX_VALUE, true)是非阻塞的,在发现文件被锁住的时候,直接返回null,并且抛出异常,如果没有锁住,直接返回该文件的文件锁。
它是共享锁,能被多个线程同时持有,它能禁止其他线程获取独占锁,可用于读文件。
while (true) {
try {
fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, true);//共享锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
独占锁lock()
而FileChannel的lock()是阻塞的,在文件被锁定的情况下,会保持阻塞,直到获得该锁为止。
fileLock = fileChannel.lock();
......
写文件线程安全
* 将str写入文件,同步操作,独占锁
public void writeStr2ReplaceFileSync(String str, String pathFile, IOListener ioListener) {
File file;
try {
file = FileUtils.createFile(pathFile);
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail("文件创建失败,请检查路径是否合法以及读写权限");
return;
FileOutputStream fileOutputStream = null;
FileChannel fileChannel = null;
FileLock fileLock = null;//文件锁
try {
* 写文件
fileOutputStream = new FileOutputStream(file);
fileChannel = fileOutputStream.getChannel();
while (true) {
try {
fileLock = fileChannel.tryLock();//独占锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
if (fileLock != null) {
int len = 0;
long current = file.length();
if (isRunning ) {
fileChannel.write(ByteBuffer.wrap(str.getBytes()));
current += len;
LogUtils.log("当前线程" + Thread.currentThread().getName());
ioListener.onLoading(str.getBytes(), current, str.length());
}else {
ioListener.onInterrupted();
if (fileLock != null && fileLock.isValid()) {
LogUtils.log("release-write-lock");
fileLock.release();
close(fileChannel);
close(fileOutputStream);
if (file.length() == str.getBytes().length) {
ioListener.onCompleted(file);
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
读文件线程安全
* 同步读取,共享锁,但无法同时进行写操作
* @param ioListener
public void read2StrSync(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
FileChannel fileChannel = null;
FileLock fileLock = null;//文件锁
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
try {
* 读文件
fileInputStream = new FileInputStream(pathFile);
fileChannel = fileInputStream.getChannel();
while (true) {
try {
fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, true);//共享锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
if (fileLock != null) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int len = 0;
long current = 0;
while (isRunning && (len = fileChannel.read(byteBuffer)) != -1) {
//0,byteBuffer.position(),必须写这个,否则GG,读取文件错乱
byteArrayOutputStream.write(byteBuffer.array(),0,byteBuffer.position());
current += len;
ioListener.onLoading("", current, fileChannel.size());
byteBuffer.clear();
if (fileLock != null && fileLock.isValid()) {
LogUtils.log("release-read-lock");
fileLock.release();
close(fileChannel);
close(fileInputStream);
if (len != -1) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(byteArrayOutputStream.toString("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
小编写的IOListener接口,用于回调
public interface IOListener<T> {
public void onCompleted(T result);
public void onLoading(T readedPart, long current, long length);
public void onInterrupted();
public void onFail(String errorMsg);
小编写的IOUtils工具类,专门用于文件读写,流的读写
public class IOUtils {
private boolean isRunning = true;
private long contentLength = 0;
private String encodeType = "utf-8";
public IOUtils() {
isRunning = true;
public IOUtils setContentLength(long contentLength) {
this.contentLength = contentLength;
return this;
public IOUtils setEncodeType(String encodeType) {
this.encodeType = encodeType;
return this;
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
public void stop() {
this.isRunning = false;
public void read(boolean isLine, InputStream inputStream, IOListener ioListener) {
if (isLine) {
readLine2String(inputStream, ioListener);
} else {
read2String(inputStream, ioListener);
* @param ioListener
public void read2String(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(pathFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
return;
read2String(fileInputStream, ioListener);
public void read2String(InputStream inputStream, IOListener ioListener) {
if (!(inputStream instanceof BufferedInputStream)) {
inputStream = new BufferedInputStream(inputStream);
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(inputStream, encodeType);
bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
char[] buf = new char[1024];
int len = 0;
long current = 0;
while (isRunning && (len = bufferedReader.read(buf)) != -1) {
sb.append(buf, 0, len);
current += len;
ioListener.onLoading("", current, contentLength);
if (len != -1) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(sb.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
close(bufferedReader);
close(inputStreamReader);
close(inputStream);
* 同步读取,共享锁,但无法同时进行写操作
* @param ioListener
public void read2StrSync(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
FileChannel fileChannel = null;
FileLock fileLock = null;//文件锁
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
try {
* 读文件
fileInputStream = new FileInputStream(pathFile);
fileChannel = fileInputStream.getChannel();
while (true) {
try {
fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, true);//共享锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
if (fileLock != null) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int len = 0;
long current = 0;
while (isRunning && (len = fileChannel.read(byteBuffer)) != -1) {
//0,byteBuffer.position(),必须写这个,否则GG,读取文件错乱
byteArrayOutputStream.write(byteBuffer.array(),0,byteBuffer.position());
current += len;
ioListener.onLoading("", current, fileChannel.size());
byteBuffer.clear();
if (fileLock != null && fileLock.isValid()) {
LogUtils.log("release-read-lock");
fileLock.release();
close(fileChannel);
close(fileInputStream);
if (len != -1) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(byteArrayOutputStream.toString("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
* @param ioListener
public void readLine2String(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(pathFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
return;
readLine2String(fileInputStream, ioListener);
* 一行一行地读
* @param inputStream
* @param ioListener
public void readLine2String(InputStream inputStream, IOListener ioListener) {
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(inputStream, encodeType);
bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
long current = 0;
String str;
while (isRunning && (str = bufferedReader.readLine()) != null) {
sb.append(str);
current += str.length();
ioListener.onLoading(str, current, contentLength);
if ((str = bufferedReader.readLine()) != null) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(sb.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
close(bufferedReader);
close(inputStreamReader);
close(inputStream);
public void readL2StrNoBuffer(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(pathFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
return;
readL2StrNoBuffer(fileInputStream, ioListener);
* 一行一行地读,不拼接
* @param inputStream
* @param ioListener
public void readL2StrNoBuffer(InputStream inputStream, IOListener ioListener) {
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(inputStream, encodeType);
bufferedReader = new BufferedReader(inputStreamReader);
long current = 0;
String str;
while (isRunning && (str = bufferedReader.readLine()) != null) {
current += str.length();
ioListener.onLoading(str, current, contentLength);
if ((str = bufferedReader.readLine()) != null) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted("");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
close(bufferedReader);
close(inputStreamReader);
close(inputStream);
public void readL_N2String(String pathFile, IOListener ioListener) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(pathFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
return;
readL_N2String(fileInputStream, ioListener);
* 一行一行地读,\n拼接
* @param inputStream
* @param ioListener
public void readL_N2String(InputStream inputStream, IOListener ioListener) {
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(inputStream, encodeType);
bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
long current = 0;
String str;
while (isRunning && (str = bufferedReader.readLine()) != null) {
sb.append(str);
sb.append("\n");
current += str.length();
ioListener.onLoading(str, current, contentLength);
if ((str = bufferedReader.readLine()) != null) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(sb.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
close(bufferedReader);
close(inputStreamReader);
close(inputStream);
* 读取到文件
* @param inputStream
* @param outputStream
* @param ioListener
public void read2File(InputStream inputStream, OutputStream outputStream, IOListener ioListener) {
try {
byte[] buffer = new byte[1024];
int len = 0;
long current = 0;
while (isRunning && (len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
current += len;
ioListener.onLoading(new String(buffer), current, contentLength);
outputStream.flush();
if (len != -1) {
ioListener.onInterrupted();
} else {
ioListener.onCompleted(null);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(outputStream);
close(inputStream);
* 将str写入文件
public void writeStr2File(String str, String pathFile, IOListener ioListener) {
BufferedWriter bufferedWriter = null;
OutputStreamWriter outputStreamWriter = null;
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(pathFile);
outputStreamWriter = new OutputStreamWriter(outputStream);
bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(str);
ioListener.onCompleted("");
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
close(bufferedWriter);
close(outputStreamWriter);
close(outputStream);
* 将str写入文件,同步操作,独占锁
public void writeStr2ReplaceFileSync(String str, String pathFile, IOListener ioListener) {
File file;
try {
file = FileUtils.createFile(pathFile);
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail("文件创建失败,请检查路径是否合法以及读写权限");
return;
FileOutputStream fileOutputStream = null;
FileChannel fileChannel = null;
FileLock fileLock = null;//文件锁
try {
* 写文件
fileOutputStream = new FileOutputStream(file);
fileChannel = fileOutputStream.getChannel();
while (true) {
try {
fileLock = fileChannel.tryLock();//独占锁
break;
} catch (Exception e) {
System.out.println("有其他线程正在操作该文件,当前线程" + Thread.currentThread().getName());
if (fileLock != null) {
int len = 0;
long current = file.length();
if (isRunning ) {
fileChannel.write(ByteBuffer.wrap(str.getBytes()));
current += len;
LogUtils.log("当前线程" + Thread.currentThread().getName());
ioListener.onLoading(str.getBytes(), current, str.length());
}else {
ioListener.onInterrupted();
if (fileLock != null && fileLock.isValid()) {
LogUtils.log("release-write-lock");
fileLock.release();
close(fileChannel);
close(fileOutputStream);
if (file.length() == str.getBytes().length) {
ioListener.onCompleted(file);
} catch (IOException e) {
e.printStackTrace();
ioListener.onFail(e.getMessage());
} finally {
写文件使用示例
new IOUtils().writeStr2ReplaceFileSync(jsonObjectOld.toJSONString(), Constants.PATH_GAME_JSON, new IOListener() {
@Override
public void onCompleted(Object result) {
@Override
public void onLoading(Object readedPart, long current, long length) {
@Override
public void onInterrupted() {
@Override
public void onFail(String errorMsg) {
读文件使用示例
new IOUtils().read2StrSync(Constants.PATH_CONFIG_APPLICATION_JSON, new IOListener<String>() {
@Override
public void onCompleted(String result) {
@Override
public void onLoading(String readedPart, long current, long length) {
@Override
public void onInterrupted() {
@Override
public void onFail(String errorMsg) {
各位老铁有问题欢迎及时联系、指正、批评、撕逼
Github:
https://github.com/AnJiaoDe
简书:
https://www.jianshu.com/u/b8159d455c69
微信公众号
NIO提升性能在JAVA的标准I/O中,提供了基于流的I/O实现,即InputStream和OutputStream。这种基于流的实现以字节为单位处理数据。NIO是New I/O的简称,表示一套新的JAVA I/O标准。在Jdk 1.4中开始引入,它具有以下特性:为所有的原始类型提供(Buffer)缓存支持; 使用Java.nio.charset.Charset作为字符集编...
文章目录Java文件系统java.ioFileInputStream & FileOutputStream对输入输出流方向的理解RandomAccessFilejava.nio.file.Files完
Java文件系统
Java内置两种文件系统:阻塞模式io和非阻塞模式nio
java.io
Java的有许多读取文件的方法,如java.io.FileReader,但基本上都是封装了java.io.FileInputStream类;写文件也是基本上封装java.io.FileOutputStream
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.OutputStream;
...
Java多线程方式复制文件**这几日有一个数据迁移需求,是说从一个系统中将所有的图片按照新的规则迁移到新的系统中来。**
思路如下1. 使用生产者模式将要下载的清单放到一个阻塞队列里面。
2. 执行消费者模式读取文件并进行处理。
其核心代码如下生产者//生产者
import java.util.concurrent.BlockingQueue;
public class Producer imple
1.如何用file操作目录和文件?
java对待目录和文件统一使用file来表示,在创建file对象时,使用isDictionary和isFile方法进行判断
1 package test;
3 import java.io.File;
5 import java.io.IOException;
7 public class FileTest {
序列化: Serialiaze 将java对象转换为二进制流ObjectOutputStream .writeObject(java对象)
反序列化: 二进制流还原java对象ObjectInputStream .readObject() --> java对象
java中要支持序列化和反序列化,需要实现接口Serializable(标记接口)
seriaVersionUID序列化版本(序列号) 当对class类做修改时,seriaVersionUID就会变动,反序列化时就会报异常,可以把
在 Java 中,多线程操作文件可以通过多种方式实现。一种常见的方法是使用 Java 内置的 java.nio 包中的类,如 FileChannel 和 MappedByteBuffer 等。
如果要以多线程的方式读取或写入文件,您可以创建多个线程,每个线程都负责读取或写入一个文件的一个特定部分。这样可以提高处理文件的速度,因为多个线程可以并行执行读写操作。
但是,在使用多线程读写文件时,需要注意并发访问问题,以防止多个线程同时写入同一个文件,从而造成文件破坏。因此,通常需要使用同步代码块或线程锁等机制来保证并发读写的安全性。
CSDN-Ada助手:
Docker无法启动 error initializing graphdriver: driver not supported
Gavin_kkkk:
一个字母占几个字节
南南很难:
sudo netstat -nltp
菜码代码: