* 栈:先进后出,后进先出
* 实现一个无锁的Stack,并写一段测试代码(多线程访问),证明这个Stack是线程安全的。给出程序以及运行的截图。
* 关键点:无锁须利用CAS类
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* 栈:先进后出,后进先出
* 实现一个无锁的Stack,并写一段测试代码(多线程访问),证明这个Stack是线程安全的。给出程序以及运行的截图。
* 关键点:无锁须利用CAS类
* Created by lizq on 2019/4/20.
*/
public class TestMain2<E> {
/**
* 存放节点数据
*
* @param <E>
*/
private class Node<E> {
/**
* 当前节点
*/
private E value;
/**
* 下一节点
*/
private Node<E> next;
/**
* 构造方法
*
* @param value
* @param next
*/
public Node(E value, Node<E> next) {
super();
this.value = value;
this.next = next;
}
/**
* 获取当前节点
*
* @return
*/
public E getValue() {
return value;
}
/**
* 设置当前节点
*
* @param value
*/
public void setValue(E value) {
this.value = value;
}
/**
* 获取下一个节点
*
* @return
*/
public Node<E> getNext() {
return next;
}
/**
* 设置下一个节点
*
* @param next
*/
public void setNext(Node<E> next) {
this.next = next;
}
}
/**
* 存放数据
*/
private AtomicReference<Node<E>> nodeStack = new AtomicReference<Node<E>>();
/**
* 验证
*/
private static AtomicInteger pj = new AtomicInteger();
private static AtomicInteger oj = new AtomicInteger();
/**
* 压入新节点(newVal),到stack中
*
* @param e
*/
public void push(E e) {
Node<E> newVal = new Node<E>(e, null);
Node<E> nowVal = null;
do {
// 获取当前栈顶节点
nowVal = nodeStack.get();
// 把新节点作为栈顶节点
newVal.setNext(nowVal);
} while ((!nodeStack.compareAndSet(nowVal, newVal)));
pj.incrementAndGet();
System.out.println("push 成功!val: " + newVal.getValue());
}
/**
* 获取当前Stack中的栈顶节点
*
* @return
*/
public E pop() {
Node<E> nowVal = null;
Node<E> nextVal = null;
do {
nowVal = nodeStack.get();
if (nowVal == null) {
// 为什么用continue 而不用break ,形成等待
continue;
}
nextVal = nowVal.getNext();
} while (nowVal == null || !nodeStack.compareAndSet(nowVal, nextVal));
oj.incrementAndGet();
return nowVal.getValue();
}
static TestMain2<Object> testMain2 = new TestMain2<Object>();
public static void main(String[] args) throws Exception {
for (int i = 0; i < 5; i++) {
new Thread("push" + i) {
@Override
public void run() {
for (int k = 0; k < 2; k++) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
testMain2.push("name:" + this.getName() + " Random->" + k);
}
}
}.start();
}
for (int i = 0; i < 4; i++) {
new Thread("pop" + i) {
@Override
public void run() {
for (int k = 0; k < 2; k++) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
System.out.println(" pop 成功!val: " + testMain2.pop());
}
}
}.start();
}
Thread.sleep(10000);
System.out.println("push num: "+pj.get());
System.out.println("pop num: "+oj.get());
}
}