设为首页 加入收藏

TOP

Java多线程(7):JUC(下)(一)
2023-07-25 21:30:12 】 浏览:45
Tags:Java JUC

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

 

除了四种常见的同步器(发令枪、摇号器、栅栏和交换机),JUC还有所谓线程安全的容器、阻塞队列和一些特殊的类。其中常出现的就是线程安全的容器和阻塞队列。与其说这是两个大的分类,还不如说它就是两个用得最多的类ConcurrentHashMapArrayBlockingQueue。

我的风格是尽量少讲原理,多讲实际生活中的案例,除非它非常重要,就像AQS,这玩意绝对是个重量级的神器,差不多整个JUC都是建立在它之上的。如果说学习多线程只有一次集中全部精力的机会的话,那我绝对建议把这份宝贵的精力花在AQS上,物超所值。至于搞明白ThreadPool底层原理、synchronized关键字原理,个人认为纯属浪费时间。因为即使弄明白了,那个机制你是改不了的,AQS原理弄明白了,可以直接拿来用,自己玩出花来。

从之前的集合类继承结构图可以知道ConcurrentHashMap继承自Map,实现了ConcurrentMap接口,它是线程安全的Map,侧重于放入或者获取的速度,而不在乎顺序。

因为现在的Java基本上都升级到了JDK1.8以上,有的甚至和官方保持同步,所以基本上很多JDK1.7及以下会出现的问题,在新的版本中都修复了,而且性能越来越好。所以只需要知道一点:在并发量比较高的环境中尽量使用ConcurrentHashMap就好了。不用弄明白为什么,因为不值得(JDK1.8的ConcurrentHashMap底层是用红黑树实现的,至于什么是红黑树,又得回头补一些基础,而且记住了也没啥用)。当然如果是为了应付面试,稍稍了解一下就好了。

为了给大家直观的印象ConcurrentHashMap怎么个线程安全法,这里那我之前的项目代码做个演示(当然是删除了很多实际需求代码,仅演示ConcurrentHashMap)。

电商里为了造一些刷单数据,需要模拟真实用户,那么就由代码产生好了:

/** * 随机姓名产生器 * * @author 湘王 */
public class RandomInfo2 { private static final String firstname = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻水云苏潘" +
            "葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳鲍史唐费岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅卞齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛" +
            "禹狄米贝明臧计成戴宋茅庞熊纪舒屈项祝董粱杜阮席季麻强贾路娄危江童颜郭梅盛林***钟徐邱骆高夏蔡田胡凌霍万柯卢莫房缪干解应宗丁" +
            "宣邓郁单杭洪包诸左石崔吉龚程邢滑裴陆荣翁荀羊甄家封芮储靳邴松井富乌焦巴弓牧隗山谷车侯伊宁仇祖武符刘景詹束龙叶幸司韶黎乔苍" +
            "双闻莘劳逄姬冉宰桂牛寿通边燕冀尚农温庄晏瞿茹习鱼容向古戈终居衡步都耿满弘国文东殴沃曾关红游盖益桓公晋楚闫"; private static final String lastname = "伟刚勇毅俊秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊兰凤洁梅琳素云莲真环" +
            "雪荣爱妹霞香月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦" +
            "岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜可姬舒影荔枝思丽峰强军平保东文" +
            "辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博诚先" +
            "敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家" +
            "致树炎德行时泰盛雄琛钧冠策腾楠榕风航弘"; /** * 随机产生姓氏 * */
    public static String getFirstName() { int strLen = firstname.length(); int index = new Random().nextInt(strLen - 1); return firstname.substring(index, index + 1); } /** * 随机产生名字 * */
    public static String getLastName() { int strLen = lastname.length(); int index = new Random().nextInt(strLen - 1); return lastname.substring(index, index + 2); } public static void count(final List<String> list, final Map<String, Integer> map) { long start = System.currentTimeMillis(); // 这里为了比较效率,特意调大了人数
        for (int i = 0; i < 10_000_000; i++) { String name = getFirstName() + getLastName(); list.add(name); } System.out.println("产生了 " + list.size() + " 个名字"); for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { list.stream().map(str -> str.substring(0, 1)).forEach(str -> { Integer count = 1; if (map.containsKey(str)) { // 多线程情况下,普通的HashMap的get()方法得到的结果可能为null // 但ConcurrentHashMap一定不会是null
                            count = map.get(str); if (null == count) { System.out.println("count == null"); } ++count; } map.put(str, count); }); System.out.println("总共 " + map.size() + " 个姓氏"); } }).start(); } int count = 0; for(Map.Entry<String, Integer> entry : map.entrySet()) { count = count + entry.getValue(); } long end = System.currentTimeMillis(); // 最后统计名字总数
        System.out.println("执行时间:" + (end - start) + " 毫秒"); } public static void main(String[] args) throws IOException { List<String> list = n
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇java Stream流练习 下一篇自从用了灰度发布,睡觉真香!

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目