MyException - 我的异常网
当前位置:我的异常网» 开源软件 » JAVA 模拟一瞬高并发

JAVA 模拟一瞬高并发

www.MyException.Cn  网友分享于:2013-11-16  浏览:0次
JAVA 模拟瞬间高并发
转载: http://blog.csdn.net/zhao9tian/article/details/40346899
前些日子接到了一个面试电话,面试内容我印象很深,如何模拟一个并发?当时我的回答虽然也可以算是正确的,但自己感觉缺乏实际可以操作的细节,只有一个大概的描述。

      当时我的回答是:“线程全部在同一节点wait,然后在某个节点notifyAll。”

      面试官:“那你听说过惊群效应吗?”

      我:“我没有听过这个名词,但我知道瞬间唤醒所有的线程,会让CPU负载瞬间加大。”

      面试官:“那你有什么改进的方式吗?”

      我:“采用阻塞技术,在某个节点将所有的线程阻塞,在利用条件,线程的个数达到一定数量的时候,打开阻塞。”

      面试官好像是比较满意,结束了这个话题。

      面试结束后,我回头这个块进行了思考,要如何进行阻塞呢?我首先有一个思路就是,利用AtoInteger计算线程数,再利用synchronize方法块阻塞一个线程,根据AtoInteger的判断,执行sleep。

      代码如下:

 

/**
* Created with IntelliJ IDEA.
* User: 菜鸟大明
* Date: 14-10-21
* Time: 下午4:34
* To change this template use File | Settings | File Templates.
*/
public class CountDownLatchTest1 implements Runnable{
final AtomicInteger number = new AtomicInteger();
volatile boolean bol = false;

@Override
public void run() {
System.out.println(number.getAndIncrement());
synchronized (this) {
try {
if (!bol) {
System.out.println(bol);
bol = true;
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("并发数量为" + number.intValue());
}

}

public static void main(String[] args) {
ExecutorService pool = Executors. newCachedThreadPool();
CountDownLatchTest1 test = new CountDownLatchTest1();
for (int i=0;i<10;i++) {
pool.execute(test);
}
}
}

 

  结果为:

 

0
2
1
4
3
false
5
6
7
8
9
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10

 

从结果上来看,应该是可以解决问题,利用了同步锁,volatile解决了同时释放的问题,难点就在于开关。

后来查找资料,找到了一个CountDownLatch的类,专门干这个的

CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则处于等待状态,调用countDown()方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行。

 

构造方法参数指定了计数的次数

 

new CountDownLatch(1)

 

countDown方法,当前线程调用此方法,则计数减一
new CountDownLatch(1)

 

awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
cdOrder.await();  

  

a直接贴代码,转载的代码
/**
 *
 * @author Administrator
 *该程序用来模拟发送命令与执行命令,主线程代表指挥官,新建3个线程代表战士,战士一直等待着指挥官下达命令,
 *若指挥官没有下达命令,则战士们都必须等待。一旦命令下达,战士们都去执行自己的任务,指挥官处于等待状态,战士们任务执行完毕则报告给
 *指挥官,指挥官则结束等待。
 */
public class CountdownLatchTest {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool(); //创建一个线程池
        final CountDownLatch cdOrder = new CountDownLatch(1);//指挥官的命令,设置为1,指挥官一下达命令,则cutDown,变为0,战士们执行任务
        final CountDownLatch cdAnswer = new CountDownLatch(3);//因为有三个战士,所以初始值为3,每一个战士执行任务完毕则cutDown一次,当三个都执行完毕,变为0,则指挥官停止等待。
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                public void run(){
                    try {
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "正准备接受命令");
                        cdOrder.await(); //战士们都处于等待命令状态
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "已接受命令");
                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "回应命令处理结果");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        cdAnswer.countDown(); //任务执行完毕,返回给指挥官,cdAnswer减1。
                    }
                }
            };
            service.execute(runnable);//为线程池添加任务
        }
        try {
            Thread.sleep((long)(Math.random()*10000));
            System.out.println("线程" + Thread.currentThread().getName() +
                    "即将发布命令");
            cdOrder.countDown(); //发送命令,cdOrder减1,处于等待的战士们停止等待转去执行任务。
            System.out.println("线程" + Thread.currentThread().getName() +
                    "已发送命令,正在等待结果");
            cdAnswer.await(); //命令发送后指挥官处于等待状态,一旦cdAnswer为0时停止等待继续往下执行
            System.out.println("线程" + Thread.currentThread().getName() +
                    "已收到所有响应结果");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        service.shutdown(); //任务结束,停止线程池的所有线程
    }
}

  执行结果:

 

线程pool-1-thread-2正准备接受命令
线程pool-1-thread-3正准备接受命令
线程pool-1-thread-1正准备接受命令
线程main即将发布命令
线程pool-1-thread-2已接受命令
线程pool-1-thread-3已接受命令
线程pool-1-thread-1已接受命令
线程main已发送命令,正在等待结果
线程pool-1-thread-2回应命令处理结果
线程pool-1-thread-1回应命令处理结果
线程pool-1-thread-3回应命令处理结果
线程main已收到所有响应结果

 

上述也是一种实现方式,用countDownLatch的await()方法,代替了synchronize 和 sleep的阻塞功能,通过countDown的方法来当做开关,和计算线程数量的一种方式。

区别的话,肯定是后者会好一些,因为第一种方式依靠sleep(xxx)来阻塞把握不好最短时间,太短了,可能来没有达到固定线程数就会打开开关。

至于两者性能上的区别,目前我还不得而知,有机会测试一下。

 

文章评论

10个调试和排错的小建议
10个调试和排错的小建议
我的丈夫是个程序员
我的丈夫是个程序员
鲜为人知的编程真相
鲜为人知的编程真相
漫画:程序员的工作
漫画:程序员的工作
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
中美印日四国程序员比较
中美印日四国程序员比较
Java程序员必看电影
Java程序员必看电影
 程序员的样子
程序员的样子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
如何成为一名黑客
如何成为一名黑客
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员必看的十大电影
程序员必看的十大电影
我是如何打败拖延症的
我是如何打败拖延症的
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
一个程序员的时间管理
一个程序员的时间管理
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
那些争议最大的编程观点
那些争议最大的编程观点
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员都该阅读的书
程序员都该阅读的书
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员应该关注的一些事儿
程序员应该关注的一些事儿
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
总结2014中国互联网十大段子
总结2014中国互联网十大段子
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
老程序员的下场
老程序员的下场
每天工作4小时的程序员
每天工作4小时的程序员
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
编程语言是女人
编程语言是女人
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有