项目使用到集群环境,流程发送时如果确保一个流程不会被两个流程同时调用?
有一种办法是用文件锁的方式来实现。
代码如下:
锁接口:
package lock;
import java.io.FileNotFoundException;
import java.io.IOException;
public interface Lock {
/**
* 检测是否被锁定
* @return true被锁定 ,false空闲
* */
public abstract boolean isLocked() throws FileNotFoundException;
/**
* 获取锁资源
* @return true成功锁定目标资源 ,false锁定操作失败
* */
public abstract boolean obtain() throws IOException;
/**
* 释放锁
* */
public abstract void unlock();
}
文件锁的实现:
package lock;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
public class FileProgrameLock implements Lock{
private String callerThreadID = null;
private String lockFileName = null;
FileChannel channel = null;
private FileLock lock = null;
public static Lock get(String fileName,String callerThreadID){
FileProgrameLock d = new FileProgrameLock(fileName);
d.callerThreadID = callerThreadID;
return (Lock)d;
}
public FileProgrameLock(String lockFileName){
this.lockFileName = lockFileName;
}
/**
* 检测是否被锁定-不建议使用
* @return true被锁定 ,false空闲
* @deprecated
* */
public boolean isLocked() throws FileNotFoundException {
File tf = new File(lockFileName);
if( ! tf.exists()){
return false;
}
FileChannel __channel = new RandomAccessFile(tf, "rw").getChannel();
FileLock tl = null;
try {
tl = __channel.tryLock();
if (tl == null) {
return true;
} else {
return false;
}
} catch (OverlappingFileLockException e) {
return true;
} catch (IOException e) {
return true;
}catch (Exception e) {
return true;
}finally{
try {
if(tl != null){
tl.release();
}
tl = null;
if(__channel.isOpen()){
__channel.close();
}
__channel = null;
tf = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取锁资源
* @return true成功锁定目标资源 ,false锁定操作失败
* */
public boolean obtain() throws IOException {
File tf = new File(lockFileName);
createFile();
channel = new RandomAccessFile(tf, "rw").getChannel();
try {
// System.out.println("get lock 000 >>>>>>>>>>>>>>>");
lock = channel.lock();
// System.out.println("get lock >>>>>>>>>>>>>>>");
return true;
} catch (OverlappingFileLockException e) {
return false;
}catch (Exception e) {
return false;
}
}
/**
* 释放锁
* */
public void unlock() {
try {
if(lock != null){
lock.release();
}
System.out.println(callerThreadID + " unlock XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ");
if(channel != null && channel.isOpen()){
channel.close();
}
lock = null;
channel = null;
this.deleteFile();
} catch (IOException e) {
}
}
protected void finalize() throws Throwable {
System.out.println(callerThreadID + this.getClass() + " .finalize()");
super.finalize();
}
private void createFile() throws IOException{
try{
File tf = new File(lockFileName);
if(! tf.exists()){
tf.createNewFile();
}
tf = null;
}catch(IOException e){
System.out.println(e+lockFileName);
throw e;
}
}
private void deleteFile(){
File tf = new File(lockFileName);
if(tf.exists()){
tf.delete();
}
tf = null;
}
}
工厂类:
package lock;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class MakeLock implements Runnable{
private String threadID = "";
public void run() {
try {
while(true) {
test2(threadID);
Thread.sleep(200);
}
} catch (IOException e) {
System.out.println(e);
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(e);
}
}
public void test2(String threadID) throws FileNotFoundException, IOException, InterruptedException{
Lock lock = new MakeLock(threadID).getLock("c:/001/lockfile001.lock",threadID);
System.out.println(threadID+":obtain...");
boolean b = lock.obtain();
//当有重叠时会发生等待,所以外侧先执行isLocked()判断
System.out.println(threadID+":obtained "+b);
if(b){//执行业务逻辑
Thread.sleep(390);
for(int i = 0 ; i < Integer.MAX_VALUE ; i ++){
;
}
lock.unlock();
}
lock = null;
}
public MakeLock(String threadID){
this.threadID = threadID;
}
public Lock getLock(String name,String threadID) {
final StringBuffer buf = new StringBuffer();
return FileProgrameLock.get(name,threadID);
}
}
使用方法:
public void test2(String threadID) throws FileNotFoundException, IOException, InterruptedException{
Lock lock = new MakeLock(threadID).getLock("c:/001/lockfile001.lock",threadID);
if (!lock.isLocked()) {
System.out.println(threadID+":obtain...");
boolean b = lock.obtain();
System.out.println(threadID+":obtained "+b);
if(b){//执行业务逻辑
Thread.sleep(390);
for(int i = 0 ; i < Integer.MAX_VALUE ; i ++){
;
}
lock.unlock();
}
}else{
System.out.println(threadID+":can't get a lock :"+lock);
}
lock = null;
}
多线程调用测试:
public static void main(String[] args) {
//new AAA().test();
System.out.println("=========================================");
Thread th1 = new Thread(new MakeLock("==================== thread1 ===================="));
Thread th2 = new Thread(new MakeLock("#################### thread2 ####################"));
Thread th3 = new Thread(new MakeLock("@@@@@@@@@@@@@@@@@@@@ thread3 @@@@@@@@@@@@@@@@@@@@"));
Thread th4 = new Thread(new MakeLock("$$$$$$$$$$$$$$$$$$$$ thread4 $$$$$$$$$$$$$$$$$$$$"));
Thread th5 = new Thread(new MakeLock("&&&&&&&&&&&&&&&&&&&& thread5 &&&&&&&&&&&&&&&&&&&&"));
th1.start();
th2.start();
th3.start();
th4.start();
th5.start();
}
=================
经测试可以在共享文件系统下工作。
附件中AAA.java多线程测试代码可以直接运行。