Java实现多线程环境下的计数器功能
来源:互联网 发布:保融软件 编辑:程序博客网 时间:2024/06/05 05:05
我们在做一个Web应用程序会遇到这样一个需求:在全局定义一个count,每次调用一个接口则count+1,用于统计接口调用次数和频率,代码入下:
public class CountServlet implements HttpServlet { private long count = 0; @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { count++; }}
上面这段代码如果在单线程环境没有问题,但是我们知道Servlet是多线程的,如果两个线程同时请求service,当线程1的count+1后,线程2进来了,这个时候count还是0,加1后得到的值还是1,这并不是我们想要的结果。有人会说在方法上面加上syncronized关键词就行了,这样做是没有问题,也能达到我们的要求。但是加上他后,线程1访问service方法后,会开启同步锁,线程2必须要等待线程1执行完成才能进行下一步操作,如果线程1执行太长或者死循环,会导致死锁,也大大影响了我们的程序性能。
在java1.5后,sun公司推出了java.util.concurrent同步包,我们可以使用这个包下面的一些类库来实现我们的需求,请看代码:
public class CountServlet implements HttpServlet { private AtomicLong count = new AtomicLong(0); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { count.incrementAndGet(); }}
AtomicLong类保证了long类型的原子性,它和syncronized不同的是,他并不是简单加上同步锁,相反,他并不会锁住当前方法。而是利用一种称之为“无锁算法”的方式,而CAS(Compare And Swap)就是非常著名的无锁算法,它的基本原理大致是这样的:它包含3个操作数,内存值V、旧的值A,要修该的新的值B,仅当A和V相同时,将V修改为B,否则什么都不做。
请看具体的代码实现:
private void compareAndSwap(int v,int a,int b){ if(v == a){ v = b; } return v; }
在java里面,它是定义的native方法,通过native方法操作机器指令,从而实现数据的原子性。
但是如果有两个线程同时访问,会不会破坏其原子性,答案是当然不会。
因为它是由若干条指令构成的,用于完成一项功能,它是连续不断的,在执行过程中不允许被中断。
以上便是Atomic包下的类库的原理,在实现这类需求的时候就可以考虑通过它去实现,既保证了性能,又保证了原子性。
- Java实现多线程环境下的计数器功能
- 多线程环境下的计数器
- java--多线程实现计数器
- java多线程环境下单利模式的实现
- Java多线程和多线程计数器的学习
- 51单片机定时/计数器的功能实现
- Java实现的高效计数器
- 解决Java多线程并发的计数器问题
- CAS实现多线程计数器
- QT环境下的多线程下载实现
- 多线程环境下的单例实现
- Android实现计数器功能
- Java多线程实现窗口售票的功能
- 多线程条件下的计数器
- 多线程条件下的计数器
- java中多线程环境下实现单例的几种方法
- Java多线程实现下载功能
- JVM运行的数据分区----程序计数器实现的功能
- oracle 游标变量ref cursor详解
- bootstrap列表js
- SourceTreeSetup-2.3.1.0.exe安装登录不了或一直卡在登录问题解决
- DataGridView
- C# WPF 文件操作
- Java实现多线程环境下的计数器功能
- laravel 5.2教程
- PYTHON3 SHA256
- 新手快速理解csdn文章编译器
- 分步骤安装lnmp完整版(带源码)
- Redis的使用场景
- aidl中没有接口函数?
- 斐波那契数的数学封闭式表示
- 使用jquery实现两个div中按钮互换位置