外贸网站建设报价差别那么大花钱多吃亏,wordpress 平铺水印,wordpress php5.3版本,深圳企业企业网站建设优质博文#xff1a;IT-BLOG-CN
【1】【强制】获取单例对象需要保证线程安全#xff0c;其中的方法也要保证线程安全。 说明#xff1a; 资源驱动类、工具类、单例工厂类都需要注意。
【2】【强制】创建线程或线程池时请指定有意义的线程名称#xff0c;方便出错时回溯。…优质博文IT-BLOG-CN
【1】【强制】获取单例对象需要保证线程安全其中的方法也要保证线程安全。 说明 资源驱动类、工具类、单例工厂类都需要注意。
【2】【强制】创建线程或线程池时请指定有意义的线程名称方便出错时回溯。 正例 自定义线程工厂并且根据外部特征进行分组比如来自同一机房的调用把机房编号赋值给whatFeaturOfGroup
public class UserThreadFactory implements ThreadFactory {private final String namePrefix; private final AtomicInteger nextId new AtomicInteger(1);// 定义线程组名称在 jstack 问题排查时非常有帮助UserThreadFactory(String whatFeaturOfGroup) {namePrefix From UserThreadFactorys whatFeaturOfGroup -Worker-;}Overridepublic Thread newThread(Runnable task) {String name namePrefix nextId.getAndIncrement();Thread thread new Thread(null, task, name, 0, false);System.out.println(thread.getName()); return thread;}
}【3】【强制】线程资源必须通过线程池提供不允许在应用中自行显式创建线程。 说明 线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销解决资源不足的问题。 如果不使用线程池有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
【4】【强制】线程池不允许使用Executors去创建而是通过ThreadPoolExecutor的方式这样的处理方式让写的同学更加明确线程池的运行规则规避资源耗尽的风险。 说明Executors返回的线程池对象的弊端如下 1FixedThreadPool和SingleThreadPool允许的请求队列长度为Integer.MAX_VALUE可能会堆积大量的请求从而导致OOM。 2CachedThreadPool 允许的创建线程数量为Integer.MAX_VALUE可能会创建大量的线程从而导致OOM。
【5】【强制】SimpleDateFormat是线程不安全的类一般不要定义为static变量如果定义为static 必须加锁或者使用DateUtils工具类。 正例注意线程安全使用DateUtils。亦推荐如下处理
private static final ThreadLocal df new ThreadLocal() {Overrideprotected DateFormat initialValue() {return new SimpleDateFormat(yyyy-MM-dd);}
};说明 如果是JDK8的应用可以使用Instant代替DateLocalDateTime代替CalendarDateTimeFormatter代替SimpleDateFormat官方给出的解释simple beautiful strong immutable thread-safe。
【6】【强制】必须回收自定义的ThreadLocal变量尤其在线程池场景下线程经常会被复用 如果不清理自定义的ThreadLocal变量可能会影响后续业务逻辑和造成内存泄露等问题。 尽量在代理中使用try-finally块进行回收。
// 正例
objectThreadLocal.set(userInfo);
try {// ...
} finally {objectThreadLocal.remove();
}【7】【强制】高并发时同步调用应该去考量锁的性能损耗。能用无锁数据结构就不要用锁能 锁区块就不要锁整个方法体能用对象锁就不要用类锁。 说明 尽可能使加锁的代码块工作量尽可能的小避免在锁代码块中调用RPC方法。
【8】【强制】对多个资源、数据库表、对象同时加锁时需要保持一致的加锁顺序否则可能会造 成死锁。 说明 线程一需要对表A、B、C依次全部加锁后才可以进行更新操作那么线程二的加锁顺序也必须是A、B、C否则可能出现死锁。
【9】【强制】在使用阻塞等待获取锁的方式中必须在try代码块之外并且在加锁方法与try代码块之间没有任何可能抛出异常的方法调用避免加锁成功后在finally中无法解锁。 说明一如果在lock方法与try代码块之间的方法调用抛出异常那么无法解锁造成其它线程无法成功 获取锁。 说明二如果lock方法在try代码块之内可能由于其它方法抛出异常导致在finally代码块中unlock对未加锁的对象解锁它会调用AQS的tryRelease方法取决于具体实现类抛出IllegalMonitorStateException异常。 说明三在Lock对象的lock方法实现中可能抛出unchecked异常产生的后果与说明二相同。
//正例
Lock lock new XxxLock(); // ...
lock.lock();
try {doSomething();doOthers();
} finally {lock.unlock();
}//反例
Lock lock new XxxLock();
// ...
try {// 如果此处抛出异常则直接执行 finally 代码块doSomething();// 无论加锁是否成功finally 代码块都会执行lock.lock();doOthers();
} finally {lock.unlock();
}【10】【强制】在使用尝试机制来获取锁的方式中进入业务代码块之前必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。 说明 Lock对象的unlock方法在执行时它会调用AQS的tryRelease方法取决于具体实现类如果 当前线程不持有锁则抛出 IllegalMonitorStateException异常。
// 正例
Lock lock new XxxLock();
// ...
boolean isLocked lock.tryLock();if (isLocked) {try {doSomething();doOthers();} finally {lock.unlock();}
}【11】【强制】并发修改同一记录时避免更新丢失需要加锁。要么在应用层加锁要么在缓存加锁要么在数据库层使用乐观锁使用version作为更新依据。 说明 如果每次访问冲突概率小于20%推荐使用乐观锁否则使用悲观锁。乐观锁的重试次数不得小于3次。
【12】【强制】多线程并行处理定时任务时Timer运行多个TimeTask时只要其中之一没有捕获抛出的异常其它任务便会自动终止运行使用 ScheduledExecutorService则没有这个问题。
【13】【推荐】资金相关的金融敏感信息使用悲观锁策略。 说明 乐观锁在获得锁的同时已经完成了更新操作校验逻辑容易出现漏洞另外乐观锁对冲突的解决策 略有较复杂的要求处理不当容易造成系统压力或数据异常所以资金相关的金融敏感信息不建议使用乐观锁更新。 正例 悲观锁遵循一锁二判三更新四释放的原则
【14】【推荐】使用CountDownLatch进行异步转同步操作每个线程退出前必须调用countDown方法线程执行代码注意catch异常确保countDown方法被执行到避免主线程无法执行至await方法直到超时才返回结果。 说明 注意子线程抛出异常堆栈不能在主线程try-catch到。
【15】【推荐】避免Random实例被多线程使用虽然共享该实例是线程安全的但会因竞争同一seed导致的性能下降。 说明 Random实例包括java.util.Random的实例或者Math.random()的方式。 正例 在JDK7之后可以直接使用API ThreadLocalRandom而在JDK7之前需要编码保证每个线 程持有一个单独的Random实例。