本文通过对实现了两个Stack,一个是基于非阻塞(Non-Blocking)算法,另一个是基于阻塞算法(Blocking)的,然后对这两个队列进行多线程环境下的大量Insert操作,通过比较二者的消耗时间,进而比较基于Volatile和CAS轮询操作的非阻塞算法和基于锁的阻塞算法在时间上的性能差异究竟有多大。
基于非阻塞算法的Stack
public class ConcurrentStack<E> {
AtomicReference<Node<E>> top = new AtomicReference<Node<E>>();
public void push(E item)
{
Node<E> newHead = new Node<E>(item);
Node<E> oldHead;
do
{
oldHead = top.get();
newHead.next = oldHead;
}while(!top.compareAndSet(oldHead, newHead));
}
public E pop()
{
Node<E> newHead;
Node<E> oldHead;
do
{
oldHead = top.get();
if(oldHead == null)
{
return null;
}
newHead = oldHead.next;
}while(!top.compareAndSet(oldHead, newHead));
return oldHead.item;
}
private static class Node<E>
{
public final E item;
public Node<E> next;
public Node(E item)
{
this.item = item;
}
}
}
阻塞算法的Stack
public class BlockingStack<E> {
Node<E> top = new Node<E>(null);
public synchronized void push(E item)
{
Node<E> newHead = new Node<E>(item);
Node<E> oldHead;
oldHead = top;
newHead.next = oldHead;
top = newHead;
}
public synchronized E pop()
{
Node<E> newHead;
Node<E> oldHead;
if(top == null)
{
return null;
}
oldHead = top;
newHead = top.next;
top = newHead;
return oldHead.item;
}
private static class Node<E>
{
public final E item;
public Node<E> next;
public Node(E item)
{
this.item = item;
}
}
}
测试代码
public class TestNonAndBlockingStack {
private int insertNums;
public TestNonAndBlockingStack(int insertNums)
{
this.insertNums = insertNums;
}
class NonBlockStackThread extends Thread
{
private ConcurrentStack<String> stack;
private CountDownLatch startGate;
private CountDownLatch endGate;
public NonBlockStackThread(ConcurrentStack<String> stack,
CountDownLatch startGate,
CountDownLatch endGate)
{
this.stack = stack;
this.startGate = startGate;
this.endGate = endGate;
}
public void run()
{
try {
startGate.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < insertNums; i++)
{
stack.push("olylakers");
}
endGate.countDown();
}
}
class BlockStackThread extends Thread
{
private BlockingStack<String> stack;
private CountDownLatch startGate;
private CountDownLatch endGate;
public BlockStackThread(BlockingStack<String> stack,
CountDownLatch startGate,
CountDownLatch endGate)
{
this.stack = stack;
this.startGate = startGate;
this.endGate = endGate;
}
public void run()
{
try {
startGate.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < insertNums; i++)
{
stack.push("oly");
}
endGate.countDown();
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int threadNums = 100;
int insertNums = 50000;
TestNonAndBlockingStack test = new TestNonAndBlockingStack(insertNums);
CountDownLatch startGateN = new CountDownLatch(1);
CountDownLatch endGateN = new CountDownLatch(threadNums);
ConcurrentStack<String> concurrentStack = new ConcurrentStack<String>();
CountDownLatch startGateB = new CountDownLatch(1);
CountDownLatch endGateB = new CountDownLatch(threadNums);
BlockingStack<String> blockingStack = new BlockingStack<String>();
for(int i = 0; i < threadNums; i++)
{
test.new NonBlockStackThread(concurrentStack, startGateN, endGateN).start();
}
long startTime = System.currentTimeMillis();
startGateN.countDown();
try {
endGateN.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("The concurrent stack push cost: "+ (System.currentTimeMillis() - startTime));
for(int i = 0; i < threadNums; i++)
{
test.new BlockStackThread(blockingStack, startGateB, endGateB).start();
}
startTime = System.currentTimeMillis();
startGateB.countDown();
try {
endGateB.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("The blocking stack push cost: "+ (System.currentTimeMillis() - startTime));
}
}
当 threadNums = 100, insertNums = 50000时,跑两次的测试结果为:
The concurrent stack push cost: 2125
The blocking stack push cost: 3657
The concurrent stack push cost: 1953
The blocking stack push cost: 3078
当 threadNums = 500, insertNums = 10000时,跑两次的测试结果为:
The concurrent stack push cost: 2141
The blocking stack push cost: 3219
The concurrent stack push cost: 2171
The blocking stack push cost: 3344
测试机器为:Core2(TM)2 Quad CPU Q9500 @2.83GHz, 4核。内存:3.25G。
分享到:
相关推荐
在现代网络编程中,非阻塞套接字(non-blocking socket)和多路复用(multiplexing)是处理高并发连接的关键技术之一。这些技术能够帮助服务器高效地管理多个客户端连接,避免因等待某个操作完成而浪费资源。本文将...
《Fast Portable non-blocking network programming with Libevent》是一本关于Libevent库的书籍,它专注于指导读者如何使用Libevent 2.0或更高版本来编写快速、可移植且支持异步I/O的网络程序。本书的作者是Nick ...
标题中的"Asynchronous, non-blocking SAP NW RFC SDK bindings for Node"是指为Node.js开发的一个库,它提供了异步、非阻塞的方式与SAP NetWeaver RFC SDK进行交互。SAP NetWeaver RFC SDK是SAP提供的一套软件开发...
标题中的"Asynchronous, non-blocking SAP NW RFC SDK bindings for Pyt" 指的是一种Python库,它提供了异步、非阻塞的接口来与SAP NetWeaver RFC(远程功能调用)SDK交互。SAP NW RFC SDK是SAP提供的一套开发工具,...
Tomcat8新版本特性: 1.支持servlet3.1, jsp 2.3, el表达式3.0 and Java WebSocket 1.0. 2.默认http与ajp请求实现non-blocking技术,即NIO技术。...6.新增AJP 连接采用了Servlet3.1的non-blocking IO。
The switch fabric delivers strictly non-blocking connectivity while completely canceling the first-order crosstalk. The 4×4 switching circuit consists of eight silicon microring-based spatial (de-)...
experiments 里面包含运行实验的运行文件,先将其他八个程序打开之后最后打开 main client new 然后让其自动运行 结果会保存在一个.txt里面。 源代码 有main client new 和 一个关于随机数生成的头文件 和 子文件
Thrift 支持 Buffered 和 Framed 二进制协议;Kitex Protobuf 是 Kitex 自定义的 Protobuf 消息协议,协议格式类似 Thrift;gRPC 是对 gRPC 消息协议的支持,可以与 gRPC 互通。除此之外,使用者也可以扩展自己的...
用法下载仓库与mvn package一起mvn package 并使用java -jar target/spring-non-blocking-io-0.0.1-SNAPSHOT.jar 调用api并等待响应。这个怎么运作实例将在几秒钟内联机。 每次调用该服务时,一个简单的Thread.sleep...
"Non-Blocking-Driving-Program" 是一个与 C++ 相关的项目,从名称来看,它可能涉及异步编程和非阻塞I/O技术。在C++中,非阻塞驱动程序通常用于提高程序效率,特别是在处理大量并发任务或者进行网络通信时,通过避免...
这个概念的引入主要是为了提高页面的滚动性能和响应速度,特别是对于移动设备上的触摸事件。Chrome浏览器从版本51开始支持这种功能。 在传统的事件监听器中,我们通常使用`addEventListener`方法添加事件处理函数,...
非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking。当对一个non-blocking socket执行读操作时,流程是这个样子: 从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还...
本文将深入探讨如何使用`addEventListener`来监听`scroll`和`touch`事件,并理解其中涉及的技术细节。 首先,我们要了解在手机上特有的`touch`事件。`touch`事件系列主要包括三个主要事件: 1. `touchstart`:当...
2. **非阻塞I/O(Non-Blocking I/O)** 非阻塞I/O模型允许线程在等待数据准备期间不被挂起,可以继续执行其他任务。在Java中,NIO(New IO)库提供了非阻塞I/O的支持。例如,`Selector`类可以监视多个通道,当数据...
Java中通过NIO(Non-blocking Input/Output)提供了对非阻塞I/O的支持,例如使用Selector和Channel等机制。 在Java中,非阻塞I/O的一个典型应用场景是网络编程,特别是服务器端。例如,使用Java NIO的...
非阻塞I/O(Non-blocking I/O)是一种处理I/O操作的方式,它不会因为等待数据准备好而使整个进程挂起。在传统的阻塞I/O模式下,当一个进程请求读取或写入数据时,如果数据尚未准备好,操作系统会让该进程进入等待...
其中,传输接口是不同模块间传输的主要接口,它包括了阻塞传输接口(blocking transport interfaces)和非阻塞传输接口(non-blocking transport interfaces)。DMI接口允许主模块直接访问从设备的内存区域,以提高...
Undertow is a Java web server based on non-blocking IO. It consists of a few different parts: A core HTTP server that supports both blocking and non-blocking IO A Servlet 4.0 implementation A JSR-356...
In data streams or web scenarios at highly variable and unpredictable rates, a good join algorithm should be able to ... The non-blocking algorithms allow some tuples to be flushed onto disk, with the go
最新版tomcat8.0,1.支持servlet3.1, jsp 2.3, el表达式3.0 and Java WebSocket 1.0. 2.默认http与ajp请求实现non-blocking技术,即NIO技术。...6.新增AJP 连接采用了Servlet3.1的non-blocking IO。