为什么有的类的start方法里会判断是否有读写锁?
2013-04-22 19:36
190 查看
如题:我们经常会看到有的类的start方法里面会有getLock()等类似的代码?这是为什么呢?什么地方需要用到这样的lock
在本人的工作中发现,比较常见的一类现象是:需要一直让某类程序长跑,即便出现异常,程序自动终止,那除了处理这些异常(比如
将对应的消息放到ExceptionMessage的Queue里面去,然后重新启动程序去处理之前的任务,当然在程序异常终止的时候,是会丢掉
部分消息。那在这种情况下,我们采用的逻辑是创建一个无限的for循环,在其中每五到十分钟调用一次脚本文件,脚本文件负责启动
线程去处理任务(比如外界传入的消息等)。但是,我们希望同一台机器上不要同时有同一脚本文件的两份实例在运行,那么这个时候
getLock()就派上用场了,它在脚本启动的时候判断是否有lock,如果有则不启动,否则启动。具体代码如下:
public void start(){
logger.info("start to transmit message from topic:{}", topicName);
StartUpLock lock = null;
try {
lock = getMsgTransmiterlock(lockFileName);
} catch (RuntimeException ex) {
logger.error("failed to get lock. lockFileName:{}", lockFileName, ex);
return;
}
if (null == lock) {
logger.info("message transmiter has been started. lockFileName:{}", lockFileName);
return;
}
}
private StartUpLock getMsgTransmiterlock(String fileName) {
StartUpLock lock = new StartUpLock(new File(lockFileName));
if (lock.lock()) {
return lock;
} else {
return null;
}
}
public class StartUpLock {
private final File file;
private FileLock lock = null;
private RandomAccessFile raf = null;
private FileChannel fc = null;
private static Logger logger = LoggerFactory.getLogger(StartUpLock.class);
public StartUpLock(File file) {
this.file = file;
}
public boolean lock(){
if(this.lock != null){
logger.warn("have already gotten lock");
return true;
}
try {
if( !file.exists() ){
File dir = file.getParentFile();
if( !dir.exists() ) dir.mkdirs();
file.createNewFile();
}
this.raf = new RandomAccessFile(this.file, "rw");
this.fc = raf.getChannel();
this.lock = fc.tryLock();
if( this.lock == null ){
logger.warn(" file have been loked, cannot get lock");
this.close();
return false;
}
return true;
} catch (FileNotFoundException e) {
logger.error("file not found", e);
this.close();
return false;
} catch (IOException e) {
logger.error("file io error", e);
this.close();
return false;
}
}
public void close(){
if( this.lock != null ){
try {
this.lock.release();
} catch (IOException e) {
logger.error("file io error", e);
}finally{
this.lock = null;
}
}
if( this.fc != null ){
try {
this.fc.close();
} catch (IOException e) {
logger.error("file io error", e);
}finally{
this.fc = null;
}
}
if( this.raf != null ){
try {
this.raf.close();
} catch (IOException e) {
logger.error("file io error", e);
} finally{
this.raf = null;
}
}
}
}
在本人的工作中发现,比较常见的一类现象是:需要一直让某类程序长跑,即便出现异常,程序自动终止,那除了处理这些异常(比如
将对应的消息放到ExceptionMessage的Queue里面去,然后重新启动程序去处理之前的任务,当然在程序异常终止的时候,是会丢掉
部分消息。那在这种情况下,我们采用的逻辑是创建一个无限的for循环,在其中每五到十分钟调用一次脚本文件,脚本文件负责启动
线程去处理任务(比如外界传入的消息等)。但是,我们希望同一台机器上不要同时有同一脚本文件的两份实例在运行,那么这个时候
getLock()就派上用场了,它在脚本启动的时候判断是否有lock,如果有则不启动,否则启动。具体代码如下:
public void start(){
logger.info("start to transmit message from topic:{}", topicName);
StartUpLock lock = null;
try {
lock = getMsgTransmiterlock(lockFileName);
} catch (RuntimeException ex) {
logger.error("failed to get lock. lockFileName:{}", lockFileName, ex);
return;
}
if (null == lock) {
logger.info("message transmiter has been started. lockFileName:{}", lockFileName);
return;
}
}
private StartUpLock getMsgTransmiterlock(String fileName) {
StartUpLock lock = new StartUpLock(new File(lockFileName));
if (lock.lock()) {
return lock;
} else {
return null;
}
}
public class StartUpLock {
private final File file;
private FileLock lock = null;
private RandomAccessFile raf = null;
private FileChannel fc = null;
private static Logger logger = LoggerFactory.getLogger(StartUpLock.class);
public StartUpLock(File file) {
this.file = file;
}
public boolean lock(){
if(this.lock != null){
logger.warn("have already gotten lock");
return true;
}
try {
if( !file.exists() ){
File dir = file.getParentFile();
if( !dir.exists() ) dir.mkdirs();
file.createNewFile();
}
this.raf = new RandomAccessFile(this.file, "rw");
this.fc = raf.getChannel();
this.lock = fc.tryLock();
if( this.lock == null ){
logger.warn(" file have been loked, cannot get lock");
this.close();
return false;
}
return true;
} catch (FileNotFoundException e) {
logger.error("file not found", e);
this.close();
return false;
} catch (IOException e) {
logger.error("file io error", e);
this.close();
return false;
}
}
public void close(){
if( this.lock != null ){
try {
this.lock.release();
} catch (IOException e) {
logger.error("file io error", e);
}finally{
this.lock = null;
}
}
if( this.fc != null ){
try {
this.fc.close();
} catch (IOException e) {
logger.error("file io error", e);
}finally{
this.fc = null;
}
}
if( this.raf != null ){
try {
this.raf.close();
} catch (IOException e) {
logger.error("file io error", e);
} finally{
this.raf = null;
}
}
}
}
相关文章推荐
- 判断两个对象是否相等,为什么必须同时重写equals()和hashcode()方法
- 为什么不能用返回值类型来判断方法是否重载呢?
- 判断两个对象是否相等,为什么必须同时重写equals()和hashcode()方法
- python脚本判断一个数是否为素数的几种方法
- 判断JavaScript对象是否可用的最正确方法分析
- Javascript 判断浏览器是否为IE的最短方法
- JAVA中判断字符是否为中文的方法
- js判断是否包含字符串的代码;转换前端显示科学记数法的方法
- Android判断当前线程是否是主线程的方法
- JS判断当前页面是否在微信浏览器打开的方法
- JavaScript判断前缀、后缀是否是空格的方法
- 如何判断当前的Fragment是否可见?Fragment的可见与不可见的判断方法。
- ORACLE中判断表或视图是否存在,如果不存在再创建的方法
- java中判断类对象是否相等的方法
- WordPress分类目录页面获取当前分类的ID及判断是否为子分类目录的方法
- 一个判断页面是否被刷方法(原创)
- Java中判断字符串是否为数字的五种方法
- Android判断后台服务是否开启的方法
- 改进项目中判断参数是否存在的方法
- 实现依据AJAX的值判断是否提交/跳转页面的方法