项目使用到集群环境,流程发送时如果确保一个流程不会被两个流程同时调用?
有一种办法是用文件锁的方式来实现。
代码如下:
锁接口:
- 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多线程测试代码可以直接运行。