该计数器支持多个客户端线程并发访问,计数器的key/value存储在一个静态型的AtomicLongMap对象中,另外有一个守护线程定期将计数器的数据取出,然后存储到数据库、文件等地方。该范例可以做适当的调整,然后应用到统计页面访问量、菜单点击量、IP访问量等计数的场景。下面是计数器的源码:
public class PageViewsStatistics { private static PageViewsStatistics pvStat = null; private static ScheduledExecutorService service = null; private static AtomicLongMap<String> pvCounterMap = AtomicLongMap.create(); //线程安全,支持并发 private static ReentrantLock lock = new ReentrantLock(); //锁 private static int MONITOR_INITIAL_DELAY_SECONDS = 3; //监控初始延迟秒数 private static int MONITOR_INTERVAL_SECONDS = 10; //监控间隔秒数 private static Map<String, Long> map2 = new HashMap<String, Long>(); /** * 计数值增加1 * @param key */ public long incr(String key){ long result = -1; while(true){ if(!lock.isLocked()){ //在做pop动作时,不能进行计数,等待直到完成pop动作 result = pvCounterMap.incrementAndGet(key); break; }else{ try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } return result; } /** * 获取单实例对象 * @return */ public static PageViewsStatistics newInstance(){ if(pvStat == null){ synchronized (PageViewsStatistics.class) { if(pvStat == null){ pvStat = new PageViewsStatistics(); } } } return pvStat; } /** * 构造函数 */ public PageViewsStatistics(){ createExecutorService(); startMonitor(); } /** * 创建计划任务线程池 */ private void createExecutorService() { if(service == null){ service = Executors.newScheduledThreadPool(1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setDaemon(true); //宿主线程 return thread; } }); } } /** * 开始监控计数器 */ private void startMonitor(){ //表示在上一个任务结束执行之后,延迟多少秒之后再执行,是从上一个任务结束时开始计算
service.scheduleWithFixedDelay( new StatMonitorRunner(), MONITOR_INITIAL_DELAY_SECONDS, MONITOR_INTERVAL_SECONDS, TimeUnit.SECONDS); } /** * 获取访问量计数器中的访问量累计值,放到一个临时Map中,然后清空访问量计数器 * @return */ private Map<String, Long> popCounter(){ Map<String, Long> newMap = new HashMap<String, Long>(); lock.lock(); try{ for(Iterator<String> it = pvCounterMap.asMap().keySet().iterator(); it.hasNext(); ){ String key = it.next(); newMap.put(key, pvCounterMap.get(key)); } pvCounterMap.clear(); }finally{ lock.unlock(); } return newMap; } class StatMonitorRunner implements Runnable{ @Override public void run() { Map<String, Long> map = popCounter(); //可以将计数值写到数据库中 for(Iterator<String> it = map.keySet().iterator(); it.hasNext(); ){ String key = it.next(); if(map2.containsKey(key)){ map2.put(key, new Long(map2.get(key).longValue() + map.get(key).longValue())); }else{ map2.put(key, map.get(key)); } } System.out.println(map2); } } }
下面是测试代码:
public class AtomicLongMapTest { public static void main(String[] args) { ScheduledExecutorService service = Executors.newScheduledThreadPool(4); for(int i=0; i<4; i++){ AtomicLongMapTest t = new AtomicLongMapTest(); service.scheduleWithFixedDelay(t.new MyRunner("name"), 0, 1000, TimeUnit.MILLISECONDS); } } class MyRunner implements Runnable{ private String name; public MyRunner(String name){ this.name = name; } @Override public void run() { long l = PageViewsStatistics.newInstance().incr(this.name); System.out.println(this.name + " > " + l); } } }
相关推荐
在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...
最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...
在IT领域,多线程和高并发是两个关键概念,特别是在Java编程中,它们对于构建高效、可扩展的系统至关重要。下面将详细解释这两个概念及其在Java中的实现和应用。 多线程是指在一个应用程序中同时运行多个独立的执行...
在编程领域,多线程是实现并发执行任务的重要手段,特别是在C++ Builder 6 (bcb6) 这样的环境中。本示例着重探讨如何在多线程环境下正确实现一个计数器,以避免线程安全问题。我们将讨论两种方法:一种可能会导致...
Java多线程代码行数计数器是一款实用的工具,主要功能是针对特定后缀名的文件进行代码行数的统计。在软件工程中,了解代码行数有时可以帮助开发者评估项目规模,跟踪代码增长,或者在性能优化时作为参考。这款工具...
### Java多线程并发实战知识点解析 #### 一、引言 在计算机科学领域,**多线程**和**并发**技术是现代软件开发中不可或缺的一部分。随着处理器核心数量的增加,利用多线程和并发可以显著提高应用程序的性能和响应...
通过这种方式,可以保证在多线程环境下,对同一个计数器的并发操作不会导致数据错误。 2. **锁机制**:另一种方法是引入锁机制。当一个客户端开始操作计数器时,获取该键的锁,完成操作后再释放。这样可以确保在...
在计算机科学中,多线程并发处理是一种编程技术,它允许多个线程在同一时间执行,从而提升程序的效率和响应速度。...具体实现将取决于代码细节,但这些基础知识点提供了一个理解多线程并发处理的起点。
Servlet线程同步计数器实验是Java Web开发中一个重要的实践课题,主要涉及到Servlet容器如何处理并发请求以及如何确保在多线程环境下的数据一致性。在这个实验中,我们将深入理解Servlet生命周期、线程模型以及线程...
"Java多线程并发执行demo代码实例" ...通过这个demo代码实例,我们学习了Java多线程并发执行的实现,包括泛型、线程池、阻塞队列和计数器等概念。这些概念可以帮助开发者编写更加高效、灵活和可重用的代码。
Java多线程并发编程是Java开发中的重要领域,特别是在服务器端和高并发应用中不可或缺。`java.util.concurrent`包提供了丰富的工具类,帮助开发者更好地管理线程和优化并发性能。以下将详细介绍标题和描述中涉及的...
### 多线程单例模式并发访问 #### 一、多线程基础概念 在讨论多线程单例模式及并发访问之前,我们先来了解一些基本概念。 **进程**和**线程**是计算机科学中的两个核心概念,它们之间的关系紧密而复杂。 - **进程...
为了克服这些限制,开发者可以考虑升级到更新的.NET框架,如VB.NET,它提供了更强大的多线程支持和更好的线程管理机制。此外,学习和理解线程同步、并发编程原则以及线程池等概念,也是提升VB多线程应用质量的关键。
多线程与高并发是计算机科学中非常重要的两个概念,它们在提高软件程序的性能、响应速度和资源利用率方面起着至关重要的作用。在当今的互联网时代,特别是在产业互联网和5G技术的推动下,多线程和高并发的应用变得...
综上所述,这个“线程并发拷贝程序”不仅展示了如何在Linux环境下利用多线程技术进行文件的并发处理,还深入探讨了线程同步、内存管理以及系统调用等多个重要的计算机科学概念。这对于理解操作系统原理、提高编程...
在C语言中,setjmp和longjmp是两个与异常处理和非局部跳转相关的函数,它们可以被用来实现一种特殊的多线程效果。虽然这两个函数并非设计为创建和管理线程的标准方法,但在某些特定场景下,它们可以模拟多线程的行为...
3.多线程并发下载图片 4.多进程并发提高数字运算 关于并发 在计算机编程领域,并发编程是一个很常见的名词和功能了,其实并发这个理念,最初是源于铁路和电报的早期工作。比如在同一个铁路系统上如何安排多列火车,...
本文将详细讨论如何利用Redis这一高性能的内存数据存储系统来实现高并发计数器,并以一个接口一天限制调用次数为例进行说明。 Redis是一个开源的键值存储系统,它支持多种数据结构,如字符串、哈希、列表、集合、...
在C#中,`System.Threading`命名空间提供了大量的类和方法来支持多线程编程,如`Thread`、`ThreadPool`、`Task`等。大漠的模板可能整合了这些工具,并进行了封装,使得开发者可以更方便地创建、管理和同步线程。 ...
- `CountDownLatch`:计数器,常用于多线程同步,例如,所有线程都完成任务后才能继续执行后续操作。 - `CyclicBarrier`:循环栅栏,允许一组线程等待其他线程到达某个点,然后一起继续执行。 4. **TCP连接与套接...