使用ConcurrentLinkedQueue惨痛的教训【转】
转自:http://blog.csdn.net/jackpk/article/details/49634577
服务端原本有个定时任务对一个集合ArrayList 中的消息做处理。 因为考虑到处理消息是先进先出原则,所以优化的时候考虑改用ConcurrentLinkedQueue 当时没仔细深入研究过这个集合就匆匆上线了。结果刚上线第二天就出问题了。服务端一次优化演变成了一个缺陷,还好及时回退了版本,后果才不是很严重。回退后对ConcurrentLinkedQueue 做了一个简单的测试代码,如下:
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ConcurrentLinkedQueueTest { private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>(); private static int count = 100000; private static int count2 = 2; // 线程个数 private static CountDownLatch cd = new CountDownLatch(count2); public static void dothis() {
for (int i = 0; i < count; i++) {
queue.offer(i);
}
} public static void main(String[] args) throws InterruptedException {
long timeStart = System.currentTimeMillis();
ExecutorService es = Executors.newFixedThreadPool(4);
ConcurrentLinkedQueueTest.dothis();
for (int i = 0; i < count2; i++) {
es.submit(new Poll());
}
cd.await();
System.out.println("cost time " + (System.currentTimeMillis() - timeStart) + "ms");
es.shutdown();
} static class Poll implements Runnable {
@Override
public void run() {
//while (queue.size() > 0) { // 效率低,每次都需要计算整个队列的个数
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
cd.countDown();
}
}
}
运行结果:
costtime 2360ms
改用while (queue.size() > 0)后运行结果:
cost time 46422ms
结果居然相差那么大,看了下ConcurrentLinkedQueue的API 原来.size() 是要遍历一遍集合的,难怪那么慢,所以尽量要避免用size而改用isEmpty().
总结了下, 在缺乏性能测试的情况下,对自己的编程要求更加要严格,特别是在生产环境下更是要小心谨慎。
使用ConcurrentLinkedQueue惨痛的教训【转】的更多相关文章
- 使用ConcurrentLinkedQueue惨痛的教训
服务端原本有个定时任务对一个集合ArrayList 中的消息做处理. 因为考虑到处理消息是先进先出原则,所以优化的时候考虑改用ConcurrentLinkedQueue 当时没仔细深入研究过这个集合就 ...
- ScrollView 尽量避免嵌套RelativeLayout,非常惨痛的教训
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...
- 记录一个bootstrap惨痛的错误
记录一个bootstrap的错误,这个错误因为我删除了一个class就导致了页面上显示的错误,这是一个惨痛的教训,特此记录,提醒自己在做前端的修改时,一定要慎之又慎.如果真的要做改动,改完之后也要测一 ...
- Gulp 常用插件
插件使用注意事项: 插件需要先 npm/cnpm install xx --save-dev gulp taskname,如果 task 已经设置成 default 的依赖,直接 gulp 即可 ta ...
- iOS---FMDB数据升级
本人在这里重要强调一下!!! 看这里,看这里,看这里,重要的事说三遍. 本人在项目开发中,由于需求问题,不得不对已经建立好的数据库进行修改(添加字段),我就很随意的直接添加了对一个的字段,运行一下,数 ...
- 【BZOJ1497】[NOI2006]最大获利 最小割
裸的最小割,很经典的模型. 建图:要求总收益-总成本最大,那么将每条弧与源点相连,流量为成本,每个收益与汇点相连,流量为收益,然后每条弧与它所能到达的收益相连,流量为inf. 与源点相连的是未被选中的 ...
- [转]浅谈CSRF攻击方式
在CSDN中看到对CSRF攻击的原理及防护文章,讲解浅显易懂,特转之: 来源:http://blog.csdn.net/fationyyk/article/details/50833620 一.CSR ...
- 浅谈CSRF攻击方式
一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSR ...
- 看完《Thinking in Java》后,我觉得自己就是一个不懂编程的小孩子,如何快速摆脱这种自卑感
我虽然不懂java也不懂程序员,但我理解这种心情.当看到自己还算自信的专业领域中一部超越自己水平很多的作品或比自己优秀太多的人,难免会感到震惊,继而进行自我否定.就像我曾经非常喜欢写作,在杂志和校报上 ...
随机推荐
- Zookeeper之Zookeeper的Client的分析
1)几个重要概念 ZooKeeper:客户端入口 Watcher:客户端注册的callback ZooKeeper.SendThread: IO线程 ZooKeeper.EventThread: 事件 ...
- windows安装php和mysql
windows安装php和mysql 测试环境:windows2008-64位主机 1.下载护卫神php一件安装包 https://www.huweishen.com/soft/php/#phpdow ...
- kafka消费者客户端启动之后消费不到消息的原因分析
如果你发现你的一个消费者客户端A已经启动了,但是就是不消费消息,此时你应该检查一下该消费者所在的组中(ConsumerGroup)是否还有其他的消费者,topic的分区可能被组中其他的消费者线程抢走( ...
- Mysql查看连接数相关信息
MySQL查看连接数相关信息在 数据库:INFORMATION_SCHEMA 表:PROCESSLIST 表结构如下: mysql> desc PROCESSLIST; +---------+- ...
- js获取系统的根路径实现介绍
js如何获取系统的根路径,在本文给出了详细的方法 function getBasePath(){ var obj=window.location; var contextPath=obj.pathna ...
- 转:linux下配置JDK提示tools.jar/dt.jar权限不够
原文:http://lkf009.iteye.com/blog/1327912 提示权限不够的原因:CLASSPATH=.;$JAVA_HOME/lib/tools.jar;$JAVA_HOME/li ...
- Python实例获取mp3文件的tag信息
下面利用一个python的实例程序,来学习python.这个程序的目的就是分析出所有MP3文件的Tag信息并输出. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- BAT-批量改文件后缀名
问题现象:在处理一个目录时,发现JPG文件都是以TMP文件命名的.双击打不开.要手动改一个为JPG. 问题处理: 1.新建一个TXT文件,内容写如下: ren *.tmp *.jpg 2.把TXT改为 ...
- WCF数据契约
当使用DataMember时,和访问符无关,及时使用了private,成员都是可见的.相反如果使用static,为不可见. 上述的两个数据成员是等效的,如果是等效的话 数据成员的顺序也必须是相同的. ...
- oracle本月、上月、去年
select trunc(sysdate, 'month') 本月第一天, trunc(last_day(sysdate)) 本月最后一天, trunc(add_month ...