zoukankan      html  css  js  c++  java
  • 《Effective Java》 学习笔记 —— 并发

      《Effective Java》第二版学习笔记之并发编程。

    第66条 同步访问共享的可变数据

      * 关键字synchronized可以保证在同一时刻只有一个线程可以执行某个方法或代码块。

      * Java语音规范保证对一个变量的读操作或者写操作是原子性(atomic,注意 i++是非原子性的,64位的long型或double型变量的读写操作也是非原子性的),但并不保证一个线程写入的值对另一个线程是可见的。

      * 避免使用Thread.stop()方法,而是采用轮询(poll)机制来终止一个线程。

      * 如果只需要线程间的交互通信,而不需要互斥,可以使用volatile关键字。

     

    第67条 避免过度同步

      * 为了避免活性失败和安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制(避免在同步区域调用不可信代码,否则容易造成死锁、异常等问题)。

      * 在同步代码块内做尽可能少的事情。

    第68条 executor 和 task 优先于线程

      * Executor service 可以等待完成一项特殊的任务再继续执行,也可以优雅的完成终止(利用awaitTerminalTermination方法),或可以在完成这些任务后逐个的获取这些任务的结果(利用ExecutorCompletionService)等。

      * 对于轻载的服务器,Executors.newCachedThreadPool通常是个不错的选择;对于高负载的服务器,最好使用Executors.newFixedThreadPool

      * 尽量不要编写自己的工作队列和直接使用线程;现在关键的抽象不再是Thread,而是工作单元(任务,task)。

      * Timer只有一个线程来执行任务,如果唯一的线程抛出了未被捕获的异常,任务就会终止。ScheduledThreadPoolExecutor 支持多个线程,并可以优雅的从抛出未受检异常的任务中恢复。

    第69条 并发工具优先于wait和notify

      * 几乎没有任何理由再使用wait和notify了。

        但并不是说不需要掌握,如维护旧代码可能还是需要了解的,此种情况下务必确保是利用标准的模式从while循环内部调用wait。一般情况下优先使用notifyAll而不是notify。

      * 使用高级工具:

        执行器框架(Executor Framework)、并发集合(Concurrent Collection)、同步器(Synchronizer,如CountDownLatch、Semaphore、CyclicBarier和Exchanger等)。

    第70条 线程安全性的文档化

      * 线程安全的级别:

        (1)不可变的(immutable):类的实例是不可变的(如String、Long、BigInteger等)。

        (2)无条件的线程安全(unconditionally thread-safe):类的实例可变,但有着足够的内部同步(如Random、ConcurrentHashMap。

        (3)有条件的线程安全(conditionally thread-safe):除了有些方法为了安全的并发使用外部同步之外,与无条件的线程安全级别相同(如 Collections.synchronized 包装返回的集合,它们的迭代器要求外部同步)。

        (4)非线程安全(not thread-safe):需外部同步(如ArrayList、HashMap等)。

        (5)线程对立(thread hostile):这个类不能安全的被多个线程并发的使用,即使所有的方法都被外部同步包围。线程对立的根源通常在于,没有同步的修改静态数据。

      * 为了避免拒绝服务攻击,应当使用一个私有锁对象(private lock object)来代替同步方法。私有锁对象只能用在无条件的线程安全类上,特别适合于专门为继承而设计的类。

    第71条 慎用延迟初始化

      * 正常的初始化优先于延迟初始化。

      * 如果出于性能的考虑而需要对静态域使用延迟初始化,就使用 lazy initiation holder class 模式:

    1 private static class FieldHolder {
    2     static final FieldType field = computeFieldValue();
    3 }
    4 
    5 static FieldType getType() {
    6     return FieldHolder.field;
    7 }

      * 如果出于性能的考虑而需要对实例域使用延迟初始化,就使用双重校验锁:

     1 // volatile 很重要,保证可见性
     2 private volatile FieldType field;
     3 
     4 FieldType getField() {
     5     FieldType result = field;
     6     if (result == null) {
     7         synchronized(this) {
     8             result = field;
     9             if (result = null) {
    10                 field = result = computeFieldValue();
    11             }
    12         }
    13     }
    14     return result;  
    15 }

    第72条 不要依赖于线程调度器

      * 不要让应用程序依赖线程调度器,也不要依赖 Thread.yield 或者线程优先级。这些设施仅仅对调度器作些暗示。

    第73条 避免使用线程组

      * 最好把线程组当作一个不成功的实验,就当它们根本不存在一样。

      * 考虑使用线程池。

    本文地址:https://www.cnblogs.com/laishenghao/p/9740851.html

  • 相关阅读:
    django分组group、user、permission
    django权限验证装饰器
    django用户和权限管理
    Selenium+python --如何定位表格中的某一个内容
    Selenium+python --定位下拉列表框并选取内容
    Selenium2+python--iframe
    Selenium3+python3--如何定位鼠标悬停才显示的元素
    Selenium3+python3--定位到元素后如何操作元素
    Selenium+python --如何定位一组元素
    补充前几天测试用到的Linux命令
  • 原文地址:https://www.cnblogs.com/laishenghao/p/9740851.html
Copyright © 2011-2022 走看看