《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 模式:
private static class FieldHolder {
static final FieldType field = computeFieldValue();
} static FieldType getType() {
return FieldHolder.field;
}
* 如果出于性能的考虑而需要对实例域使用延迟初始化,就使用双重校验锁:
// volatile 很重要,保证可见性
private volatile FieldType field; FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result = field;
if (result = null) {
field = result = computeFieldValue();
}
}
}
return result;
}
第72条 不要依赖于线程调度器
* 不要让应用程序依赖线程调度器,也不要依赖 Thread.yield 或者线程优先级。这些设施仅仅对调度器作些暗示。
第73条 避免使用线程组
* 最好把线程组当作一个不成功的实验,就当它们根本不存在一样。
* 考虑使用线程池。
本文地址:https://www.cnblogs.com/laishenghao/p/9740851.html
《Effective Java》 学习笔记 —— 并发的更多相关文章
- Effective Java 学习笔记之第七条——避免使用终结(finalizer)方法
避免使用终结方法(finalizer) 终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的. 不要把finalizer当成C++中析构函数的对应物.java中,当对象不 ...
- Effective Java 阅读笔记——并发
66:同步访问共享的可变数据 synchronized:1互斥,阻止线程看到的对象处于不一致的状态:2保证线程在进入同步区时能看到变量的被各个线程的所有修改 Java中,除了long或者double, ...
- Effective Java学习笔记
创建和销毁对象 第一条:考虑用静态工厂方法替代构造器 For example: public static Boolean valueOf(boolean b){ return b ? Boolean ...
- Effective Java 学习笔记之所有对象都通用的方法
一.覆盖equals时请遵守通用约定 1.满足下列任何一个条件时,不需要覆盖equals方法 a.类的每个实例本质上都是唯一的.此时就是Object中equals方法所表达的含义. b.不关心类是否提 ...
- Effective Java 学习笔记之创建和销毁对象
一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法 ...
- Effective Java 学习笔记----第7章 通用程序设计
第7章 通用程序设计 第29条 将局部变量的作用域最小化 使一个局部变量的作用域最小化,最有力的技术室在第一次使用它的地方声明. 第30条 了解和使用库 效率提高.如果你不知道库 ...
- effective java学习笔记之不可实例化的类
在没有显式声明一个类的构造方法时,编译器会生成默认的无参构造方法,在设计工具类时,我们通常将方法设置成静态方法,以类名.方法名的形式调用,此时这个类就没有必要创建实例,我们知道抽象类不可以被实例化,但 ...
- Effective Java学习笔记--创建和销毁对象
创建和销毁对象 一.静态工厂方法代替构造器 静态工厂方法的优缺点 优点: 1.可以自定义名称(可以将功能表述的更加清晰) 2.不必每次调用都创建新的对象(同一对象重复使用) 3.返回的类型可以是原返回 ...
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- java学习笔记14--多线程编程基础1
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...
随机推荐
- “由于这台计算机没有终端服务器客户端访问许可证”解决方案
由于windows2003默认仅支持2个终端用户的登陆.当"终端连接超出了最大连接"的情况出现导致不能登录. 1.在另外一台Windows2003的机器上运行"tsmmc ...
- SQL Server Replication 总结
合并复制中,数据库架构的更改要重新生成发布端的快照 在SQL Server 合并复制中,如果在发布端做了数据库架构的更改(例如新建表,更改表结构等),原则上来说都需要重新生成发布端的快照,订阅端才能同 ...
- SharePoint读取配置文件
配置文件存放目录 C:\inetpub\wwwroot\wss\VirtualDirectories\80\web.config 读取配置 string Name=Configuration.WebC ...
- Django之cookie&session
cookie Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息 ...
- python基础学习16----模块
模块(Module)的引入 import 模块名 调用模块中的函数的方式为 模块名.函数名 这种方式引入会相当于将模块中代码执行一遍,所以如果引入的模块中有输出语句,那么只写import 模块名,运行 ...
- Go语言学习笔记(四)结构体struct & 接口Interface & 反射reflect
加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...
- 分享-结合demo讲解JS引擎工作原理
代码如下: var x = 1; function A(y){ var x = 2; function B(z){ console.log(x+y+z); } return B; } var C = ...
- 用python实现MRO算法
引子: 如图反映了python3中,几个类的继承关系和查找顺序.对于类A,其查找顺序为:A,B,E,C,F,D,G,(Object),这并不是一个简单的深度优先或广度优先的规律.那么这个顺序到底是如何 ...
- Nowcoder 提高组练习赛-R7
Nowcoder 提高组练习赛-R7 https://www.nowcoder.com/acm/contest/179#question 中间空了两场,因为实在是太难了... 第五场的第二题好像还比较 ...
- docker容器下tomcat 不向catalina.out输出日志解决以及支持中文字符集
docker容器下tomcat 不向catalina.out输出日志解决 去掉 & 符号,直接 使用 ENTRYPOINT ["/data/tomcat/bin/startup.sh ...