Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- /**
- * Locking linked list allows it to be used by multiple threads without causing issues with concurrent modifications.
- * This implementation uses locks to prevent other threads from using the list
- * Locking has major performance drawbacks such as when a thread is accessing the list other threads that might wanna use it
- * will end up waiting in line for the operations to be completed.
- *
- * @param <T> the type to be stored.
- */
- public class LockingLinkedList<T> {
- private int size = 0;
- private Node<T> head;
- /**
- * we use this lock at the beginning of a method call to make sure any other thread
- * calling the method will have to wait for the one who called it before.
- * <p>
- * And at the end of the call to release the lock so the waiting thread can start executing the method
- */
- private final Lock lock = new ReentrantLock();
- /**
- * Since this method has more than one return statement
- * we would have to make sure we release the lock before every return statement
- */
- private boolean delete(T value) {
- // Lock the method.
- lock.lock();
- // Store head node
- Node<T> prev = null;
- Node<T> currNode = this.head;
- //
- // CASE 1:
- // If head node itself holds the key to be deleted
- if (currNode != null && value.equals(currNode.value)) {
- this.head = currNode.next; // Changed head
- size--;
- // release the lock
- lock.unlock();
- return true;
- }
- //
- // CASE 2:
- // If the key is somewhere other than at head
- //
- // Search for the key to be deleted,
- // keep track of the previous node
- // as it is needed to change currNode.next
- while (currNode != null && !value.equals(currNode.value)) {
- // If currNode does not hold key
- // continue to next node
- prev = currNode;
- currNode = currNode.next;
- }
- // If the key was present, it should be at currNode
- // Therefore the currNode shall not be null
- if (currNode != null && prev != null) {
- // Since the key is at currNode
- // Unlink currNode from linked list
- prev.next = currNode.next;
- size--;
- // release the lock
- lock.unlock();
- return true;
- }
- //
- // CASE 3: The key is not present
- //
- // release the lock
- lock.unlock();
- return false;
- }
- public void add(T value) {
- // lock the method
- lock.lock();
- // Create a new node with given data
- Node<T> newNode = new Node<>(value, null);
- // If the Linked List is empty,
- // then make the new node as head
- if (this.head == null) {
- this.head = newNode;
- } else {
- // Else traverse till the last node
- // and insert the newNode there
- Node<T> last = this.head;
- while (last.next != null) {
- last = last.next;
- }
- // Insert the newNode at last node
- last.next = newNode;
- }
- size++;
- // release the lock
- lock.unlock();
- }
- public int size() {
- return size;
- }
- public T head() {
- return head.value;
- }
- public T tail() {
- Node<T> last = this.head;
- while (last.next != null) {
- last = last.next;
- }
- return last.value;
- }
- private static class Node<V> {
- V value;
- Node<V> next;
- public Node(V value, Node<V> next) {
- this.next = next;
- this.value = value;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement