1, 读写锁
(1)读锁与读锁不互斥, 即一个拥有lock锁的读锁的线程在读a变量时, 另一个同样拥有lock锁的读锁的线程可以同时读a变量
(2)读锁与写锁互斥, 即一个拥有lock锁的读锁的线程在读a变量时,另一个同样拥有lock锁的写锁的线程不可以同时修改a变量, 反之亦然
(3)写锁与写锁互斥, 即一个拥有lock锁的读锁的线程在读a变量时,其他拥有lock锁(无论读锁或写锁)的线程都不能读或者写a变量
2, 此链表没有主动的调用垃圾回收机制, 如果此链表的节点数量很多很多, 同时又频繁的增加,删除节点, 会大量内存浪费
package util;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 单向链表<br>
* 许多超出索引范围的异常我没有处理, 会抛出空指针异常.<br>
* 加上了线程锁, 保证操作的同步性(同步性在下没有自测,不保证没bug).<br>
* 没有添加删除尾节点的方法,因为是单向列表,只能从上一个节点找到下一个节点,要实现也可以,只是我懒
* @author xiezc
* @date 2016-3-31 下午1:12:27
*
*/
public class LinkList<T> {
/**
* 定义一个头节点
*/
private Node first; // 定义一个头结点
/**
* 定义尾节点
*/
private Node finalNode;// 定义尾节点
/**
* 读写锁
*/
private ReadWriteLock rwl = new ReentrantReadWriteLock(); // 读写锁:上面有一个读锁和一个写锁
/**
* 插入一个头节点
*
* @param data
* @author xiezc
* @throws Exception
*/
public boolean addFirstNode(T data) {
Node node = new Node(data);
rwl.writeLock().lock();
try {
if (first == null) {
first = node;
finalNode = node;
node.setNext(null);
} else {
node.setNext(first);
first = node;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
rwl.writeLock().unlock();
}
}
/**
* 删除一个头结点,并返回头结点
*
* @return
* @author xiezc
*/
public T deleteFirstNode() {
rwl.writeLock().lock();
try {
Node tempNode = first;
// 此处可以直接用"=="比较,相当于C++中的指针.下同
if (first == finalNode) {// 只有一个节点
first = tempNode.getNext();
finalNode = null;
}
first = tempNode.getNext();
return tempNode.get();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
rwl.writeLock().unlock();
}
}
/**
* 获得指定索引的节点<br>
* 递归调用:<br>
* 1,递归要有停止条件(不然会一直循环下去).<br>
* 2:递归的每次返回值要对应与此次的index索引(当然也可以返回错位的索引(index+1)值,但是要小心处理错位的边界情况)
*
* @param index
* 如果index大于链表的总数量,则返回的是null
* @return
* @author xiezc
*/
private Node getNodeByIndex(int index) {
// 没有判断index<0的情况,因为此方法只被getByIndex()方法调用.
rwl.readLock().lock();
try {
if (index == 0) {// 停止条件
return first;
}
if (index == 1) {// 停止条件
return first.getNext();// 返回的都是当前索引的值
}
Node node = getNodeByIndex(index - 1);// 获得node是index-1对应的值
return node.getNext();// 返回的都是当前索引index对应的值
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
rwl.readLock().unlock();
}
}
/**
* 获得指定索引的节点<br>
*
* @param index
* 如果index大于链表的总数量,则返回的是null
* @return
* @author xiezc
*/
public T getByIndex(int index) {
if (index < 0)
throw new RuntimeException("索引index不能小于零:" + index);
return getNodeByIndex(index).get();
}
/**
* 在任意位置之后插入节点 在index的后面插入
*
* @param index
* 如果index超出节点数量,则添加在尾节点后面
* @param data
* @author xiezc
*/
public boolean add(int index, T data) {
if (index < 0)
throw new RuntimeException("索引index不能小于零:" + index);
if (index == 0) {
return addFirstNode(data);
}
Node node = new Node(data);
rwl.writeLock().lock();
try {
// 获得索引处节点
Node current = getNodeByIndex(index);
if (current == finalNode) {// 索引处的节点就是最终节点(包括只有一个节点的情况)
finalNode.setNext(node);
finalNode = node;
}
if (current == first && finalNode != current) {// 两个节点以上的情况,且current不是最终节点
Node next = current.getNext();
current.setNext(node);
node.setNext(next);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
rwl.writeLock().unlock();
}
}
/**
* 删除任意位置的节点,并且返回删除的节点
*
* @param index
* 如果index超出节点数量则返回空的节点,并且没有实现删除
* @return
* @author xiezc
*/
public T delete(int index) {
if (index < 0)
throw new RuntimeException("索引index不能小于零:" + index);
if (index == 0) {
return deleteFirstNode();
}
rwl.writeLock().lock();
try {// 主要锁住last的值的改变
// 获得指定位置处的上一个节点
Node last = getNodeByIndex(index - 1);
// 当前节点
Node current = last.getNext();
if (current == null) {// current刚好为空的情况,其实此处可不要,
// 因为下面的Node next = current.getNext();会报空指针异常
throw new java.lang.ArrayIndexOutOfBoundsException(index);
}
// 下一个节点
Node next = current.getNext();
if (next == null) {// 说明要删除的节点刚好是最终节点
last.setNext(null);
return current.get();
}
last.setNext(next);
return current.get();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
rwl.writeLock().unlock();
}
}
/**
* 添加尾节点
*
* @param data
* @author xiezc
*/
public boolean addFinalNode(T data) {
if (finalNode == null) {
return addFirstNode(data);
}
Node node = new Node(data);
rwl.writeLock().lock();
try {
finalNode.setNext(node);
finalNode = node;
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
rwl.writeLock().unlock();
}
}
/**
* 节点的内部类
* @author xiezc
*
*/
class Node {
private Node next;
private T t;
public Node(T t) {
this.t = t;
}
public T get() {
return t;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}