1.获取单例对象需要保证线程安全,其中的方法也要保证线程安全。(资源驱动类、工具类、单例工厂类都需要注意)
2.线程池不允许使用Executor去创建,而好似通过ThreadPoolExecutor的方式,这样的处理方式会让程序猿更加明确线程池的运行规则,避免资源耗尽的风险。Exxcutors返回的线程池对象的弊端有如下:
1)FixedThreadPool和SingleThreadPool:
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2)CacheThreadPool和ScheduledThreadPool:
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
3)高并发时,同步调用应该考量锁的性能损耗。能用无锁数据结构,就不要用锁;能 锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
4)对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则会造成死锁。
5)并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据。(如果每次访问冲突的概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重复次数不得小于3次)
6)避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争统一seed导致的性能下降。在JDK7之后,可以直接使用API ThreadLocalRandom,而在JDK7之前,需要编码保证每个线程持有一个实例。(Random实例包括java.util.Random的实例或者Math.random()的方式)
7)HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中可以使用其他数据结构或加锁来避免此风险。
JAVA并发处理注意事项
最新推荐文章于 2023-03-24 16:48:45 发布