首页 > 编程语言 >编程规约-并发处理

编程规约-并发处理

时间:2022-09-23 20:44:20浏览次数:44  
标签:变量 规约 编程 并发 ThreadLocal 实例 线程 使用 new

编程规约-并发处理

线程安全

保证线程安全

获取单例对象需要保证线程安全,其中的方法也要保证线程安全。

说明:资源驱动类、工具类、单例工厂类都需要注意。

SimpleDateFormat 是线程不安全的类

SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。

正例:注意线程安全,使用 DateUtils。亦推荐如下处理:

    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,

DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。

使用 ScheduledExecutorService 处理并行定时任务

多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。

volatile 解决多线程内存不可见问题

对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。

说明:如果是 count++操作,使用如下类实现:

AtomicInteger count = new AtomicInteger();
count.addAndGet(1);

如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。

HashMap resize 时可能出现死链

HashMap 在容量不够进行 resize 时 由于高并发可能出现死链,导致 CPU 飙升,在开发过程中注意规避此风险。

确保 countDown 方法被执行到

使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown 方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行至 await 方法,直到超时才返回结果。

说明:注意,子线程抛出异常堆栈,不能在主线程 try-catch 到。

排错

线程名称

创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。

正例:自定义线程工厂,并且根据外部特征进行分组,比如,来自同一机房的调用,把机房编号赋值给 whatFeatureOfGroup

package com.gcbeen.concurrent;


import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class UserThreadFactory implements ThreadFactory {
    private final String namePrefix;
    private final AtomicInteger nextId = new AtomicInteger(1);

    // 定义线程组名称,在利用 jstack 来排查问题时,非常有帮助
    UserThreadFactory(String whatFeatureOfGroup) {
        namePrefix = "From UserThreadFactory's " + whatFeatureOfGroup + "-Worker-";
    }

    @Override
    public Thread newThread(Runnable task) {
        String name = namePrefix + nextId.getAndIncrement();
        Thread thread = new Thread(null, task, name, 0);
        System.out.println(thread.getName());
        return thread;
    }
}

线程池

线程资源必须由线程池提供

线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

说明:线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。

如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

线程池不允许使用 Executors 去创建

线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors 返回的线程池对象的弊端如下:

1) FixedThreadPool 和 SingleThreadPool:

允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

2) CachedThreadPool:

允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

ThreadLocal 变量

必须回收自定义的 ThreadLocal 变量

必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,

如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。

尽量在代码中使用 try-finally 块进行回收。

正例:

objectThreadLocal.set(userInfo);
try {

    // ...

} finally {

    objectThreadLocal.remove();

}

避免 Random 实例被多线程使用

避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一 seed 导致的性能下降。

说明:Random 实例包括 java.util.Random 的实例或者 Math.random()的方式。

正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要编码保证每个线程持有一个单独的 Random 实例。

ThreadLocal 对象使用 static 修饰,ThreadLocal 无法解决共享对象的更新问题。

说明:这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享此静态变量,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只要是这个线程内定义的)都可以操控这个变量。

标签:变量,规约,编程,并发,ThreadLocal,实例,线程,使用,new
From: https://www.cnblogs.com/gcbeen/p/16724181.html

相关文章

  • 编程规约-集合处理
    编程规约-集合处理泛型集合泛型定义集合泛型定义时,在JDK7及以上,使用diamond语法或全省略。说明:菱形泛型,即diamond,直接使用<>来指代前边已经指定的类型。正例://......
  • 编程规约-处理Map List Set
    编程规约-处理MapListSetMapCollectors类的toMap()方法相同键相关联的值之间的冲突在使用java.util.stream.Collectors类的toMap()方法转为Map集合时,一定要使......
  • 编程语言界的丐帮 C#.NET FRAMEWORK 4.6 EF 连接MYSQL
    1.nuget引用 EntityFramework、和 MySql.Data.EntityFramework。  MySql.Data这个库视情况。2.新建实体类:usingSystem;usingSystem.ComponentModel.DataAnnot......
  • 编程小知识
    在编程的过程中总会遇到各种各样的小问题,问题虽然不大,有时候也很头疼,在这里有个小小的记录python之PEP8规范在使用pycharm过程中,有时候代码会突然出现红色或者黄色的波......
  • 面向对象编程(OOP)与面向过程编程(POP)
    面向对象编程(OOP)与面向过程编程(POP)10个主要区别面向对象编程(OOP)和面向过程编程(POP)之间的关系。大家好,今天我要讲的10个主要区别面向对象编程(OOP)和面向过程编程(POP)之......
  • Java并发之ReentrantLock基础(一)
    ReentrantLock是Java中java.util.concurrent.locks.Lock的一个实现类,顾名思义它是Java中锁的一种实现,具体一点来说它是Java中一种可重入的独占锁。它与synchronized相比在......
  • 结对编程评价对方
    本次结对编程我和杨锐坚一对。 过程中,对方认真负责,帮助我纠正了不少代码规范问题。 在关于页面跳转的实现方式中提出了比较规范的方法:自定义的页面对象继承SWING中的......
  • 快速上手React编程 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1R4B-izNpESydo-yFNmU8xw点击这里获取提取码 ......
  • 【Springboot之切面编程】自定义注解实现入参指定枚举值校验
    通过自定义枚举注解@EnumValidator(value=SexEnums.class),privateIntegersex;就可以校验入参值必须在指定枚举类中原创:https://www.jianshu.com/p/32f0d6e3afbb......
  • 【Springboot之切面编程】注解实现接口防刷
    本文介绍一种极简洁、灵活通用接口防刷实现方式、通过在需要防刷的方法加上@Prevent注解即可实现短信防刷;使用方式大致如下:/***测试防刷**@para......