Java中的文件锁
Contents
假设这情况情况, 同一台服务器上有个服务有两个进程(一般用作负载均衡, 以及在更新时切换使用). 有个定时任务, 但只需要其中之一执行就可以了.
添加一个注解类
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface FileLock {
}
添加一个AOP类
import com.google.common.hash.Hashing;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
@Aspect
@Component
public class FileLockAspect {
private static final Logger log = LoggerFactory.getLogger(FileLockAspect.class);
@Pointcut("@annotation(你的包名.FileLock)")
public void lockAspect() {
// aspect point
}
@Around("lockAspect()")
public void doBefore(ProceedingJoinPoint jp) throws Throwable {
final String key = jp.toLongString();
final String hashCode = Hashing.sipHash24().hashBytes(key.getBytes()).toString();
final File lockFile = new File("/tmp/" + hashCode + ".flock");
if (!lockFile.exists()) {
final boolean ok = lockFile.createNewFile();
if (!ok) {
log.error("can not create file {}. ", lockFile.getName());
System.exit(-1);
}
}
final RandomAccessFile randomAccessFile = new RandomAccessFile(lockFile, "rw");
final FileChannel fileChannel = randomAccessFile.getChannel();
FileLock fileLock = null;
try {
fileLock = fileChannel.tryLock();
if (fileLock == null || !fileLock.isValid()) {
log.info("other instance running....");
return;
}
jp.proceed();
} finally {
if (fileLock != null && fileLock.isValid()) {
log.info("release lock...{}", lockFile.getName());
fileLock.release();
}
fileChannel.close();
}
}
}
你的任务类
@FileLock
@Scheduled(cron = "0 */3 * * * *")
public void check() {
....
}
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>