Follow these steps to implement the example:
- Create a class named MyAbstractQueuedSynchronizer that extends the AbstractQueuedSynchronizer class:
public class MyAbstractQueuedSynchronizer extends
AbstractQueuedSynchronizer {
- Declare a private AtomicInteger attribute named state:
private final AtomicInteger state;
- Implement the constructor of the class to initialize its attribute:
public MyAbstractQueuedSynchronizer() {
state=new AtomicInteger(0);
}
- Implement the tryAcquire() method. This method tries to change the value of the state variable from zero to one. If it can, it returns the true value; else, it returns false:
@Override
protected boolean tryAcquire(int arg) {
return state.compareAndSet(0, 1);
}
- Implement the tryRelease() method. This method tries to change the value of the state variable from one to zero. If it can, it returns true; else, it returns false:
@Override
protected boolean tryRelease(int arg) {
return state.compareAndSet(1, 0);
}
- Create a class named MyLock and specify that it implements the Lock interface:
public class MyLock implements Lock{
- Declare a private AbstractQueuedSynchronizer attribute named sync:
private final AbstractQueuedSynchronizer sync;
- Implement the constructor of the class to initialize the sync attribute with a new MyAbstractQueueSynchronizer object:
public MyLock() {
sync=new MyAbstractQueuedSynchronizer();
}
- Implement the lock() method. Call the acquire() method of the sync object:
@Override
public void lock() {
sync.acquire(1);
}
- Implement the lockInterruptibly() method. Call the acquireInterruptibly() method of the sync object:
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
- Implement the tryLock() method. Call the tryAcquireNanos() method of the sync object:
@Override
public boolean tryLock() {
try {
return sync.tryAcquireNanos(1, 1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
return false;
}
}
- Implement another version of the tryLock() method with two parameters: a long parameter named time and a TimeUnit parameter named unit. Call the tryAcquireNanos() method of the sync object:
@Override
public boolean tryLock(long time, TimeUnit unit) throws
InterruptedException {
return sync.tryAcquireNanos(1, TimeUnit.NANOSECONDS
.convert(time, unit));
}
- Implement the unlock() method. Call the release() method of the sync object:
@Override
public void unlock() {
sync.release(1);
}
- Implement the newCondition() method. Create a new object of the internal class of the sync object, namely ConditionObject:
@Override
public Condition newCondition() {
return sync.new ConditionObject();
}
- Create a class named Task and specify that it implements the Runnable interface:
public class Task implements Runnable {
- Declare a private MyLock attribute named lock:
private final MyLock lock;
- Declare a private String attribute called name:
private final String name;
- Implement the constructor of the class to initialize its attributes:
public Task(String name, MyLock lock){
this.lock=lock;
this.name=name;
}
- Implement the run() method of the class. Acquire the lock, put the thread to sleep for 2 seconds, and then release the lock object:
@Override
public void run() {
lock.lock();
System.out.printf("Task: %s: Take the lock ",name);
try {
TimeUnit.SECONDS.sleep(2);
System.out.printf("Task: %s: Free the lock ",name);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
- Implement the main class of the example by creating a class named Main with a main() method:
public class Main {
public static void main(String[] args) {
- Create a MyLock object named lock:
MyLock lock=new MyLock();
- Create and execute 10 Task tasks:
for (int i=0; i<10; i++){
Task task=new Task("Task-"+i,lock);
Thread thread=new Thread(task);
thread.start();
}
- Try to get the lock using the tryLock() method. Wait for a second, and if you don't get the lock, write a message and try again:
boolean value;
do {
try {
value=lock.tryLock(1,TimeUnit.SECONDS);
if (!value) {
System.out.printf("Main: Trying to get the Lock ");
}
} catch (InterruptedException e) {
e.printStackTrace();
value=false;
}
} while (!value);
- Write a message indicating that you got the lock and release it:
System.out.printf("Main: Got the lock ");
lock.unlock();
- Write a message indicating the end of the program:
System.out.printf("Main: End of the program ");