把对象封装到一个线程里,只有这个线程能看到这个对象。html
Ad-hoc 线程封闭:程序控制实现,最糟糕,忽略
堆栈封闭:局部变量,无并发问题
ThreadLocal 线程封闭:特别好的封闭方法java
ThreadLocal 实例保存登陆用户信息编程
public class RequestHolder { private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>(); /** * 添加数据 * 在filter里将登陆用户信息存入ThreadLocal * 若是不使用ThreadLocal,咱们会须要将request一直透传 * @param id */ public static void add(Long id){ // ThreadLocal 内部维护一个map,key为当前线程名,value为当前set的变量 requestHolder.set(id); } /** * 获取数据 * @return */ public static Long getId(){ return requestHolder.get(); } /** * 移除变量信息 * 若是不移除,那么变量不会释放掉,会形成内存泄漏 * 在接口处理完之后进行处理(interceptor) */ public static void remove(){ requestHolder.remove(); } }
1.StringBuilder 线程不安全,StringBuffer线程安全
缘由:StringBuffer几乎全部的方法都加了synchronized关键字。安全
2.SimpleDateFormat
SimpleDateFormat 在多线程共享使用的时候回抛出转换异常,应该才用堆栈封闭在每次调用方法的时候在方法里建立一个SimpleDateFormat。
另外一种方式是使用joda-time的DateTimeFormatter(推荐使用)。多线程
3.ArrayList,HashMap,HashSet等Collections并发
4.先检查再执行高并发
// 非原子性 if(condition(a)){ handle(a); }
如今使用的比较少,主要使用并发容器。
ArrayList->Vector,Stack
HashMap->HashTable工具
Collections.synchronizedXXX (list,set,map)ui
J.U.C下的工具类:【并发编程】【JDK源码】JDK的(J.U.C)java.util.concurrent包结构线程
ArrayList->CopyOnWriteArrayList
HashSet/TreeSet->CopyOnWriteArraySet/ConcurrentSkipListSet
HashMap/TreeMap->ConcurrentHashMap/ConcurrentSkipListMap
安全地共享对象包括如下几种策略:
线程限制:一个被线程限制的对象,由线程独占,而且只能被占有它的线程修改。
共享只读:一个共享只读的对象,在没有额外同步的状况下,能够被多个线程并发访问,可是任何线程都不能修改它。
线程安全对象:一个线程安全的对象或者容器,在内部经过同步机制来保证线程安全,因此其余线程无需额外的同步就能够经过公共接口随意访问它。
被守护对象:被守护对象只能经过获取特定的锁来访问。
参考资料:
慕课网高并发实战(六)- 线程安全策略