package threads.lock; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; import threads.deadlock.OverdrawnException; public class TimeoutTrylockDemo { private static final int NUM_ACCOUNTS = 10; private static final int NUM_THREADS = 20; private static final int NUM_ITERATIONS = 100000; private static final int LOCK_TIMEOUT = 1; static final Random rnd = new Random(); List<Account> accounts = new ArrayList<Account>(); public static void main(String args[]) { TimeoutTrylockDemo demo = new TimeoutTrylockDemo(); demo.setUp(); demo.run(); } void setUp() { for (int i = 0; i < NUM_ACCOUNTS; i++) { Account account = new Account(i, 1000); accounts.add(account); } } void run() { for (int i = 0; i < NUM_THREADS; i++) { new BadTransferOperation(i).start(); } } class BadTransferOperation extends Thread { int threadNum; BadTransferOperation(int threadNum) { this.threadNum = threadNum; } @Override public void run() { int transactionCount = 0; for (int i = 0; i < NUM_ITERATIONS; i++) { Account toAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS)); Account fromAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS)); int amount = rnd.nextInt(1000); if (!toAccount.equals(fromAccount)) { boolean successfulTransfer = false; try { successfulTransfer = transfer(fromAccount, toAccount, amount); } catch (OverdrawnException e) { successfulTransfer = true; } if (successfulTransfer) { transactionCount++; } } } System.out.println("Thread Complete: " + threadNum + " Successfully made " + transactionCount + " out of " + NUM_ITERATIONS); } private boolean transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException { boolean success = false; try { if (fromAccount.tryLock(LOCK_TIMEOUT, TimeUnit.MILLISECONDS)) { try { if (toAccount.tryLock(LOCK_TIMEOUT, TimeUnit.MILLISECONDS)) { success = true; fromAccount.withDrawAmount(transferAmount); toAccount.deposit(transferAmount); } } finally { toAccount.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); } finally { fromAccount.unlock(); } return success; } } }