java文件锁的实现

项目使用到集群环境,流程发送时如果确保一个流程不会被两个流程同时调用?

有一种办法是用文件锁的方式来实现。

代码如下:

锁接口:

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多线程测试代码可以直接运行。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值