Fork me on GitHub

Java并发编程实战

注意:所有文章除特别说明外,转载请注明出处.

[TOC]

第十一章 Java并发编程实战

11.1 生产者和消费者模式

提示:生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。

生产者和消费者彼此之间不直接通信,而是通过阻塞队列来进行通信,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中取。所以这里的阻塞队列相当于一个缓冲区,平衡生产者和消费者的处理能力。

11.2 ArrayBlockingQueue

11.3 并发组件ConcurrentHashMap使用注意事项

在ConcurrentHashMap中的方法map.putIfAbsent()方法添加新设备列表时,如果在key在map中不存在,则将key与对应的值放入map中。注意的是这个操作是原子性操作,放入后会返回null。

如果key在map中存在,则调用putIfAbsent()会返回key对应的value值。如果发现返回的value值不是null则将新的value值添加到返回的列表里面,从而问题得到解决。

总结:put(K key, V value)方法判断,如果key已经存在,则使用value覆盖原来的值并返回原来的值。如果key不存在则将value放入并返回null。putIfAbsent(K key, V value)方法则是如果key已经存在则直接返回原来对应的值并不使用value覆盖,如果key不存在则放入value并返回null。另外需要注意的是,判断key是否存在和放入是原子操作。

11.4 SimpleDateFormat 是线程不安全的

SimpleDateFormat是Java提供的一个格式化和解析日期的工具类,但是它不是线程安全的。所以在多线程程序中共用一个SimpleDateFormat实例对日期进行解析或者格式化会导致程序出错。

原因

由于多线程使用的是一个calendar对象,所以线程A执行程序之后,线程B再次执行可能是线程A清空的对象,从而导致程序错误。

解决方案

1. 每次使用时候new一个SimpleDateFormat的实例,这样可以保证每个实例使用自己的Calendar实例。

    这样的过程由于没有其它的引用,需要回收,开销很大

2. 可使用synchronized进行同步

    这样的方式同样也意味着多个线程要竞争锁,在高并发场景下会导致系统响应性能下降。

3. ThreadLocal 这样每个线程只需要使用一个SimpleDateFormat实例

11.5 使用Timer时需要注意的事情

当一个Timer运行多个TimerTask时,只要其中一个TimerTask在执行中向run()方法外抛出了异常,则其它任务也会自动终止。

11.5.2 Timer实现原理分析

TaskQueue是一个由平衡二叉树堆实现的优先级队列,每个Timer对象内部有一个TaskQueue队列。

用户线程调用Timer的schedule()方法就是将TimerTask任务添加到TaskQueue队列。

在调用schedule()方法时,long delay参数表示任务延迟多少时间执行。

注意:TimerThread是具体执行任务的线程,是从TaskQueue队列里面获取优先级最高的任务进行执行。只有执行完当前的任务才会从队列里面获取下一个任务,不管队列是否有任务已经到了设置的delay时间。一个Timer只有一个TimerThread线程,所以在Timer的内部实现是一个 多生产者-单消费者模型。

其实如果需要Timer功能,使用ScheduleThreadPoolExecutor的schedule()是比较好的选择。如果在ScheduledThreadPoolExecutor中的一个任务抛出异常,其它任务不受影响。

提示:ScheduledThreadPoolExecutor的其它任务不受抛出异常任务的影响,是因为在ScheduledThreadPoolExecutor中的ScheduledFutureTask任务中catch掉了异常。

11.6 使用ThreadLocal不当会导致内存泄漏

ThreadLocal只是一个工具类,具体存放变量的是线程的threadLocals变量。

threadLocals变量是一个ThreadLocalMap类型变量,

11.7 线程池使用FutureTask时需要注意的事情

线程池在使用FutrueTask时如果将拒绝策略设置为 DiscardPolicy 和 DiscardOldestPolicy,并且在被拒绝的任务的Future对象上调用了无参get()方法,那么调用线程会一直被阻塞。

本文标题:Java并发编程实战

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:16:22

原始链接:http://bangjinhu.github.io/undefined/第11章 Java并发编程实战/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.