java并发读写链表_单链表java单链表的实现, 多线程 ,读写锁

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;

/**

* 单向链表

* 许多超出索引范围的异常我没有处理, 会抛出空指针异常.

* 加上了线程锁, 保证操作的同步性(同步性在下没有自测,不保证没bug).

* 没有添加删除尾节点的方法,因为是单向列表,只能从上一个节点找到下一个节点,要实现也可以,只是我懒

* @author xiezc

* @date 2016-3-31 下午1:12:27

*

*/

public class LinkList {

/**

* 定义一个头节点

*/

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();

}

}

/**

* 获得指定索引的节点

* 递归调用:

* 1,递归要有停止条件(不然会一直循环下去).

* 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();

}

}

/**

* 获得指定索引的节点

*

* @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;

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值