【进阶】-Java读写文件锁

路飞
路飞
路飞
43
文章
14
评论
2019年9月23日12:36:37 评论 431 2566字阅读8分33秒

众所周知,Java中锁的概念是非常重要的,锁可以保证资源的安全可控,恰当使用锁即可使得资源高效利用,又能保证线程的安全访问,编程中在读取文件的时候常常碰到文件锁的使用,本文简单阐述文件锁在Java中的使用范例,代码仅供参考。

FileLock文件锁

public abstract class FileLock implements AutoCloseable {……}

 Locks are associated with files, not channels. Use locks to coordinate with external processes, not between threads in the same JVM.

public static String readChannel(final File file, final String encoding) {
	final StringBuilder builder = new StringBuilder();
	FileLock fileLock = null;
	// FileInputStream will throws java.nio.channels.NonWritableChannelException
	try(RandomAccessFile ra = new RandomAccessFile(file, "rw"); FileChannel fileChannel = ra.getChannel())
	{
		do
		{
			fileLock = fileChannel.tryLock();
		} while (null == lock);

		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while ((fileChannel.read(buffer)) != -1)
		{
			buffer.flip(); // Flip buffer
			builder.append(Charset.forName(setCharset(encoding)).decode(buffer));
			buffer.clear();
		}
		// release resource
		fileLock.release();
	} catch (IOException e)
	{
		e.printStackTrace();
	} 
	return builder.toString();
}

public static void writeChannel(final File file, final String data, final String encoding) {
	try(FileOutputStream fos = new FileOutputStream(file); 
			FileChannel fileChannel = fos.getChannel(); 
			FileLock fileLock = fileChannel.lock()/*无参lock()为独占锁*/)
	{
		fileChannel.write(ByteBuffer.wrap(data.getBytes(setCharset(encoding))));
	} catch (IOException e)
	{
		e.printStackTrace();
	}
}

对于这个锁有如上表述,明确指出此锁用于不同JVM之间的进程来限制文件的读写,而非多线程之间的读写。那么多线程之间读写锁用哪个呢?答案是ReadWriteLock

ReadWriteLock读写锁

public interface ReadWriteLock{……}

 顾名思义,此锁作为读写锁用于相同JVM的线程间读写文件操作。而此锁的实现,诸如:可重入的读写锁(ReentrantReadWriteLock)是比较常用的。

public class FileLockUtil {	
	private final static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private final static String DEFAULT_ENCODING = "UTF-8";

	public static void write(final File file, final String data, final String encoding) {
		lock.writeLock().lock();
		try(OutputStreamWriter writer = new OutputStreamWriter(
				new BufferedOutputStream(new FileOutputStream(file)), Charset.forName(setCharset(encoding))))
		{
			writer.write(data);
			writer.flush();
		} catch (IOException e)
		{
			e.printStackTrace();
		} finally
		{
			lock.writeLock().unlock();
		}
	}
	
	public static String read(final File file, final String encoding) {
		lock.readLock().lock();
		final StringBuilder builder = new StringBuilder();
		try(InputStreamReader reader = new InputStreamReader(
				new BufferedInputStream(new FileInputStream(file)), Charset.forName(setCharset(encoding))))
		{
			char[] buffer = new char[1024];
			int len = -1;
			while ((len = reader.read(buffer)) != -1)
			{
				builder.append(buffer, 0, len);
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}  finally
		{
			lock.readLock().unlock();
		}
		return builder.toString();
	}
		
	private static String setCharset(final String encoding) {
		return Optional.ofNullable(encoding).orElse(DEFAULT_ENCODING);
	}
}
继续阅读
weinxin
微信公众号
分享IT信息技术、北海生活的网站。提供北海本地化的信息技术服务。
路飞
  • 本文由 发表于 2019年9月23日12:36:37
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
Tomcat增加管理账户 信息技术

Tomcat增加管理账户

默认情况下,Tomcat的管理功能是关闭的,如何开启? 使用文本编辑工具打开 ${TOMCAT_HOME}\conf\tomcat-users.xml 文件,在最下面可以看到Tomcat默认把用户以及...
Windows10扩展分区大小 信息技术

Windows10扩展分区大小

1       前言 由于应用程序的不断积累,导致系统盘的空间不断被消耗,如何扩展其空间的大小呢? 通过Windows 10的磁盘管理可以轻松完成这项任务,假设要扩展C盘,那么需要将与C盘相连的分区删...
Java库之Lombok的妙用 JAVA编程

Java库之Lombok的妙用

Lombok是目前比较流行的Java库,Lombok能以简单的注解形式来简化Java代码,提高开发人员的开发效率,免去额外的getter或equals等方法,降低由于修改引起的维护成本,Lombok在...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: