`
gaddma
  • 浏览: 17114 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA多线程计数器的问题

 
阅读更多

现在web程序的计数器的应用场景比较多,分布式计数器可以使用redis,但是作为java程序员就会考虑怎么使用单节点多线程实现一个计数器。

 

计数器有两个层次的要求

1,多个线程访问不会造成计数器数值丢失

2,是否对计数器返回的值有要求,比如打印,比如用这个值做些事情

 

如果要满足2的话,那只有一种方式就是加锁,把相应的代码块加锁

 

如果要满足1的话,有两种思路,一个使用Java的并发包里面的atomic类型,一种是使用volatile变量然后使用sychronized变量。

因此有了如下两个程序

程序1

 

package com.fb.concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

public class MutiThreadCount implements Callable<Long> {

	private AtomicInteger ai = new AtomicInteger();

	public MutiThreadCount() {
	}

	@Override
	public Long call() {
		Long start = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			ai.incrementAndGet();
		}
		Long end = System.currentTimeMillis();
		return end - start;

	}

	public static void main(String[] args) throws InterruptedException,
			ExecutionException {
		ExecutorService es = Executors.newFixedThreadPool(1000);
		Long maxtime = 0l;
		MutiThreadCount mtc = new MutiThreadCount();
		List<Future<Long>> result = new ArrayList<Future<Long>>();
		for (int i = 0; i < 1000; i++) {
			Future<Long> time = es.submit(mtc);
			result.add(time);
		}

		es.shutdown();

		for (Future<Long> f : result) {
			Long time = f.get();
			if (time > maxtime) {
				maxtime = time;
			}
		}
		System.out.println(maxtime);
		System.out.println(mtc.ai.get());
	}

}

 

 

程序2:

 

package com.fb.concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MutiThread1Count implements Callable<Long> {

	private int counting;

	@Override
	public Long call() {
		Long start = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			incr();
		}
		Long end = System.currentTimeMillis();
		return end - start;

	}

	public synchronized void incr() {
		counting++;
	}

	public static void main(String[] args) throws InterruptedException,
			ExecutionException {
		Long start = System.currentTimeMillis();
		ExecutorService es = Executors.newFixedThreadPool(1000);

		MutiThread1Count mtc1 = new MutiThread1Count();
		List<Future<Long>> result = new ArrayList<Future<Long>>();
		for (int i = 0; i < 1000; i++) {
			Future<Long> time = es.submit(mtc1);
			result.add(time);
		}

		es.shutdown();
		Long maxtime = 0l;
		Long total = 0l;
		for (Future<Long> f : result) {
			Long time = f.get();
			if (time > maxtime) {
				maxtime = time;
			}
			total += time;
		}
		System.out.println("avg time is :" + total / result.size());
		System.out.println(maxtime);
		System.out.println(mtc1.counting);
		Long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

}

 

 

 

但是,在本机环境(intel I7 4核8线程)执行的时候,第一个程序可以吃到100%的cpu,第二个程序最多使用4个cpu线程,而且还不会到100%。

 

简单的理解就是:第一个程序不阻塞,全线程的跑,第二个线程synchronized会有可能导致每次都会重选进入锁的程序。

 

 

但是还是比较质疑这个想法:volatile变量使用比较脆弱,第二种调用效率按说应该比第一个高,参考:

www.ibm.com/developerworks/cn/java/j-jtp06197.html

 

为什么呢?

 

 

分享到:
评论

相关推荐

    java多线程代码行数计数器

    代码多线程计数器,可以搜索指定后缀名的文件。最小化到托盘的时候有点问题,有的系统无法显示小图标,但是不影响使用。

    Java多线程之并发工具类

     1)CountDownLatch(同步倒数计数器:等待多线程(或者多步骤)完成)  2)CyclicBarrier(循环屏障:同步屏障)  3)Semaphore(信号量:控制并发进程数)  主要参考资料:java并发编程的艺术、Java并发——...

    poi多线程大数据导出excel文件.zip

    对大数据量的导出excel,用多线程,用倒数计数器对文件进行生成,使用poi,可以支持大数据量的生成,项目中使用的poi是3.1的,上传的是4.1的。

    详解java多线程的同步控制

    同步控制是并发程序必不可少的重要手段,本文我们将通过重入锁、读写锁、信号量、倒计数器和循环栅栏以及他们的实例来介绍Java并发程序中的同步控制。 目录线程安全 Thread Safety重入锁 ReentrantLock读写锁 ...

    多线程笔记.docx

    详细的Java多线程笔记,一共17章,能够让你更加了解多线程.线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

    java学习多线程处理

    多线程开发的优势:改善用户体验,提高资源利用率(单线程的处理效率低下) 线程的使用步骤:定义一个线程,创建线程的实例,启动线程,终止线程 主线程:(java中所有的线程都是java.lang.Thread类或者其子类的一...

    多线程操作实例源码,,

    浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。  多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望...

    多线程操作实例源码

    浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。  多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望...

    使用Java的Memory Model实现一个简单的计数器.txt

    这个代码实现了一个简单的计数器,使用了Java的`AtomicInteger`类来保证多线程环境下的原子性操作。`AtomicInteger`是一个支持原子操作的整数类,它内部使用了CAS(Compare And Swap)算法来实现线程安全的操作。在...

    第 3 次JAVA上机 报 告

    编写Java代码实现一个计数器类Counter, 其中包含: 域counterValue 用来保存计数器的当前数值 方法increment(), 计数器加一 方法decrement(), 计数器减一 方法reset(), 计数器清零 3.编程实现矩形类,其中包括...

    C#的多线程机制探索

    一.多线程的概念  Windows是一个多任务的系统,如果你使用的是windows...浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。

    2020最新Java面试题及答案(带完整目录).pdf

    JVM 允许一个应用并发执行多个线程。 Hotspot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系。当线程本地存储、缓 冲区分配、同步对象、栈、程序计数器等准备好以后,就会创建一个操作系统原生线程。 Java ...

    Java语言多线程

    一,多线程概述。...Java语言的重要特征是在语言级支持多线程的程序设计。 二,多线程的生命周期。 三,创建线程的四种方式 1.继承Thread类。如下图所示。 2.实现Runnable接口。如下图所示。   3.使用Calla

    Java开发技术大全(500个源代码).

    ThreadImRunnable.java 继承Runnable接口实现多线程 mulThread.java 创建多个线程对象的类 demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类...

    深入理解高并发编程-Java线程池核心技术

    线程与多线程 1.线程 在操作系统中,线程是比进程更小的能够独立运行的基本单位。同时,它也是 CPU 调度的基本单位。线程本身基本上不拥有系统资源,只是拥有一些在运行时 需要用到的系统资源,例如程序计数器,...

    VC学习笔记之四:多线程知识.doc

    Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,...浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。

    java源码包---java 源码 大量 实例

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA上百实例源码以及开源项目源代码

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java虚拟机运行时数据区

     java虚拟机多线程是使用线程轮流切换并分配处理执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。为了线程切换后能够恢复到正确的执行位置,每条线程都需要一套独立的线程...

Global site tag (gtag.js) - Google Analytics