Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Java Re-Entrant Lock [Snippets]

DZone's Guide to

Java Re-Entrant Lock [Snippets]

Want to learn more about using the Java re-entrant lock feature? Check out this post to learn more about how to implement this feature in your Java project.

· Java Zone ·
Free Resource

Atomist automates your software deliver experience. It's how modern teams deliver modern software.

This code sample looks at the usage of the Java re-entrant lock feature that can be utilized for a FundTransferService. Let's take a look!

 Account.Java that holds lock:

import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

public class Account implements Serializable {

private static final long serialVersionUID = -935328553578153571L;
private long accountId;
private String customerName;
private AtomicLong balance = new AtomicLong(0L);
private ReentrantLock lock = new ReentrantLock();

public Account(long acId, long bal, String cName) {
accountId = acId;
customerName = cName;
balance.set(bal);
}

public ReentrantLock getLock() {
return lock;
}

public long getAccountId() {
return accountId;
}

public String getCustomerName() {
return customerName;
}

public long getBalance() {
return balance.get();
}

public void setBalance(long balance) {
this.balance.set(balance);
}
}


 FundTransferService:

import java.util.concurrent.TimeUnit;

public class FundTransferService {

/** One Second time out */
private static final long TIMEOUT_INTERVAL = 5 * 1000;

public static boolean transferFund(Account from, Account to, long amount) throws FundTransferException {
boolean haveMoney = haveEnoughBalence(from, amount);
boolean success = false;
if (haveMoney) {
boolean doTry = true;
long tryTime = System.currentTimeMillis() + TIMEOUT_INTERVAL;
while (doTry) {
try {
if (from.getLock().tryLock(100, TimeUnit.MILLISECONDS)) {
if (to.getLock().tryLock(100, TimeUnit.MILLISECONDS)) {
from.setBalance(from.getBalance() - amount);
to.setBalance(to.getBalance() + amount);
doTry = false;
success = true;
break;
}
}
if (System.currentTimeMillis() > tryTime) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.TRANSACTION_TIMEOUT);
}
} catch (InterruptedException ie) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.SERVICE_UNAVAILABLE);
} finally {
if (success) {
to.getLock().unlock();
from.getLock().unlock();
}
}
}
}
return success;
}

public static boolean deposit(Account account, long amount) throws FundTransferException {
return doDepositOrWithdraw(account, amount, true);
}

public static boolean withdraw(Account account, long amount) throws FundTransferException {
boolean haveMoney = haveEnoughBalence(account, amount);
if (haveMoney) {
return doDepositOrWithdraw(account, amount, false);
}
return false;
}

private static boolean doDepositOrWithdraw(Account account, long amount, boolean isDeposit)
throws FundTransferException {
boolean doTry = true;
long tryTime = System.currentTimeMillis() + TIMEOUT_INTERVAL;
boolean success = false;
while (doTry) {
try {
if (account.getLock().tryLock(100, TimeUnit.MILLISECONDS)) {
long balance = isDeposit == true ? account.getBalance() + amount : account.getBalance() - amount;
account.setBalance(balance);
doTry = false;
success = true;
break;
}
if (System.currentTimeMillis() > tryTime) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.TRANSACTION_TIMEOUT);
}
} catch (InterruptedException ie) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.SERVICE_UNAVAILABLE);
} finally {
if (success) {
account.getLock().unlock();
}
}
}
return success;
}

private static boolean haveEnoughBalence(Account account, long amount) throws FundTransferException {
boolean doTry = true;
long tryTime = System.currentTimeMillis() + TIMEOUT_INTERVAL;
boolean haveMoney = false;
boolean gotLock = false;
while (doTry) {
try {
if (account.getLock().tryLock(100, TimeUnit.MILLISECONDS)) {
gotLock = true;
if (account.getBalance() < amount) {
haveMoney = false;
throw new FundTransferException(FundTransferException.ERROR_COEDE.INSUFFICIENT_BALENCE);
} else {
haveMoney = true;
break;
}
}
if (System.currentTimeMillis() > tryTime) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.TRANSACTION_TIMEOUT);
}
} catch (InterruptedException ie) {
throw new FundTransferException(FundTransferException.ERROR_COEDE.SERVICE_UNAVAILABLE);
} finally {
if (gotLock) {
account.getLock().unlock();
}
}
}
return haveMoney;
}
}


 FundTransferException:

public class FundTransferException extends Exception {

enum ERROR_COEDE {

INSUFFICIENT_BALENCE("Insufficent Balance"), TRANSACTION_TIMEOUT("Transaction Timed Out"), SERVICE_UNAVAILABLE(
"Service Unavailable");
private String errorMessage;

ERROR_COEDE(String message) {
errorMessage = message;
}

};

private ERROR_COEDE erroCode;
private Exception originalException;

public FundTransferException(Exception ex, ERROR_COEDE ec) {
originalException = ex;
erroCode = ec;
}

public FundTransferException(ERROR_COEDE ec) {
erroCode = ec;
}

public ERROR_COEDE getErroCode() {
return erroCode;
}

public Exception getOriginalException() {
return originalException;
}

public static void main(String[] args) {
System.out.println(FundTransferException.ERROR_COEDE.INSUFFICIENT_BALENCE.errorMessage);
}

}


 TestFundTransfer:

public class TestFundTransferService {

public static void main(String[] args) {
testTransferFundSucess();
testTransferFundNoBalance();
testTransferTimeOut();
testWithdrawSucess();
testWithdrawNoBalance();
testWithdrawTimeOut();
testDepositSucess();
testDepositTimeOut();
}

private static void testTransferFundSucess() {
Account mathew = new Account(1001, 10000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
try {
FundTransferService.transferFund(mathew, reeba, 3000);
} catch (FundTransferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("testTransferFundSucess");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testTransferFundNoBalance() {
Account mathew = new Account(1001, 2000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
try {
FundTransferService.transferFund(mathew, reeba, 3000);
} catch (FundTransferException e) {
System.out.println(e.getErroCode().name());
}
System.out.println("testTransferFundNoBalance");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testTransferTimeOut() {
Account mathew = new Account(1001, 1000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
Thread t1 = new Thread(new Runnable() {

@Override
public void run() {
try {
FundTransferService.transferFund(mathew, reeba, 3000);
} catch (FundTransferException e) {
System.out.println(e.getErroCode().name());
}
}
});
mathew.getLock().lock();
t1.start();
try {
t1.join();
} catch (InterruptedException ie) {

}
System.out.println("testTransferTimeOut");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testWithdrawSucess() {
Account mathew = new Account(1001, 10000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
try {
FundTransferService.withdraw(mathew, 3000);
FundTransferService.withdraw(reeba, 4000);
} catch (FundTransferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("testWithdrawSucess");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testWithdrawNoBalance() {
Account mathew = new Account(1001, 2000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
try {
FundTransferService.withdraw(mathew, 3000);
FundTransferService.withdraw(mathew, 13000);
} catch (FundTransferException e) {
System.out.println(e.getErroCode().name());
}
System.out.println("testWithdrawNoBalance");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testWithdrawTimeOut() {
Account mathew = new Account(1001, 1000, "Mathew George");
Thread t1 = new Thread(new Runnable() {

@Override
public void run() {
try {
FundTransferService.withdraw(mathew, 3000);
} catch (FundTransferException e) {
System.out.println(e.getErroCode().name());
}
}
});
mathew.getLock().lock();
t1.start();
try {
t1.join();
} catch (InterruptedException ie) {

}
System.out.println("testTransferTimeOut");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("==============================================");
}

private static void testDepositSucess() {
Account mathew = new Account(1001, 10000, "Mathew George");
Account reeba = new Account(1002, 10000, "Reeba Mathew");
try {
FundTransferService.deposit(mathew, 3000);
FundTransferService.deposit(reeba, 4000);
} catch (FundTransferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("testWithdrawSucess");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("Balance - Reeba " + reeba.getBalance());
System.out.println("==============================================");
}

private static void testDepositTimeOut() {
Account mathew = new Account(1001, 1000, "Mathew George");
Thread t1 = new Thread(new Runnable() {

@Override
public void run() {
try {
FundTransferService.deposit(mathew, 3000);
} catch (FundTransferException e) {
System.out.println(e.getErroCode().name());
}
}
});
mathew.getLock().lock();
t1.start();
try {
t1.join();
} catch (InterruptedException ie) {

}
System.out.println("testTransferTimeOut");
System.out.println("Balance - Mathew " + mathew.getBalance());
System.out.println("==============================================");
}

}


Get the open source Atomist Software Delivery Machine and start automating your delivery right there on your own laptop, today!

Topics:
java concurrency ,java ,code ,reentrant ,lock ,reentrant lock ,snippet ,snippets

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}