刚刚,在iteye博客里看了一下,散仙的几篇文章好像都挨在一起,不知道这篇文章发了之后,会不会刷屏,实在是不好意思啊。 上班没时间,只能利用下班的时间,留在公司,给大家分享一些有用的技能,也算散仙比较懒吧,散仙实在不愿意晚上回到宿舍之后,再尼玛研究什么技术,我草,那样岂不真的成码农了。
好了,扯淡了几句,下面开始进入正题,本篇散仙要分享的关于NIO里面的文件锁的知识,文件锁的用处,在特定场景下,是非常有用的,那么在开始进行讲解之前,散仙,先借这个知识,来给大家分享一下文件锁在lucene里面发挥的巨大作用。如果想要学习lucene4.x的朋友们,可以参照散仙的博客学习哦。
我们都知道lucene的索引存储,可以放在跟操作系统有关的文件系统里的,而lucene呢,又是决不允许有多个线程同时进行并发写的操作的,那么lucene又不像一些关系型数据库可以采取,锁表,锁行等等一些加锁策略来同步写入操作,那它到底是采用是什么实现的呢?答案毫无疑问,就是采用我们的文件系统加锁策略来实现的,可能用过lucene,solr或es的一些朋友们,有时会发现在我们索引的目录里,莫名其妙的出现了一个以.lock结尾的锁文件,没错,当出现这个文件时,就已经证明你肯定进行过数据的写入操作,
那么可能有些读者还有个疑问,为什么我的锁文件一直都存在啊?我的服务都已经停了呀,它怎么还有呢,我可以不可以把它删除呀?....,别着急,听散仙慢慢的给你介绍下实际情况,大多数时候,我们执行完写入操作后,这个锁文件是会自动删除的,如果它没有自动删除,那么就可能出现如下的几种情况,第一,程序出异常,突然中断了,第二,在写入操作依旧进行的时候我们强制关闭服务了,第三,断电或系统崩溃了。第四,有可能我们写的程序,忘关闭流资源了,造成资源引用依然存在。由以上几种情况,都有可能造成.lock文件没有被lucene自动删除,这时候我们可以手动删除,当然删不删除它,都不影响我们正常使用程序的。你要觉得它留在那里,有损形象,那么你就放心大胆的把它删除吧,当然前提是,不要在有写入操作进行的时候,去删除它。
当然,上面只是散仙分析的一个在lucene中的锁案例,其实这个文件锁,在很多场景都大有用处,因为在某种程度上来说,它可以简洁完美的防止并发。
下面,散仙先给一张,测试用的锁文件目录:
测试,代码如下:
class="java">package com.filelock;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
/***
*
* @author 秦东亮
* 测试文件锁的功能
*
* **/
public class MyLock {
public static void main2(String[] args)throws Exception {
File f=new File("D://6//mylock.lock");
f.delete();
}
public static void main(String[] args)throws Exception {
// List<String> s=Files.readAllLines(Paths.get("D://6//my.txt"), StandardCharsets.UTF_8);
//System.out.println(s.size());
//使用FileOutputStream获取channel
FileOutputStream f=new FileOutputStream(new File("D://6//mylock.lock"));
FileChannel channel=f.getChannel();
//非阻塞加锁
FileLock lock=channel.tryLock();
//阻塞加锁
// FileLock lock=channel.lock();
if(lock==null){
System.out.println("改程序已经被占用.....");
System.out.println("阻塞中.....");
}else{
System.out.println("开始访问.......");
Thread.sleep(5000);//5秒后进行访问
if(lock!=null){
List<String> s=Files.readAllLines(Paths.get("D://6//my.txt"), StandardCharsets.UTF_8);
//读取文件,打印内容
for(String ss:s){
System.out.println(ss);
}
lock.release();//释放锁
lock.close();//关闭资源
f.close();//关闭流资源
Files.delete(Paths.get("D://6//mylock.lock"));
System.out.println("访问完毕删除锁文件");
}
}
}
}
运行时的目录状态,截图如下:
控制台打印效果如下:
开始访问.......
?有经验
有关系
有技术
有资本
oh了,你可以去创业了!
访问完毕删除锁文件
最后,我们大家都可以测试一下,让sleep休眠的时间更长一点,然后启动一个程序去访问这个文件,就会报一个异常,该文件已经被占用什么的,现在,我们就可以利用文件锁,来防止写入的并发操作了,至于具体的什么场景,还跟各位大大的业务有关系了。不过在高并发的场景下,建议还是使用一些关系型数据库,或者一些Nosql来解决,做做缓存,负载均衡什么的。总之,一句话,具体场景,具体分析。BOSS们看的都是结果,不会关心你的过程。
好了,今天,散仙就先分享到这里了,感谢各位看官,能够坚持看到最后。
- 大小: 75.7 KB
- 大小: 51.5 KB