校验注解和常用注解备忘等

10 篇文章 0 订阅
7 篇文章 0 订阅

1 实体类校验注解

依赖

        <dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

1. 时间

(1) @DateTimeFormat(pattern = “yyyy-MM-dd”)

@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate effectDay;
"effectDay": "2027-10-16"

(2) @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)

查询时自动将数据库中的data类型转换为yyyy-MM-dd HH:mm:ss,一般常使用在响应实体

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")// 中国GMT+8
    private LocalDate createTime;
/**
 * 疫苗响应实体
 */
@Data
public class CowsVaccineVO implements Serializable {
    /**
     * 接种时间
     */
    @ApiModelProperty("接种时间")
//    @JsonFormat(shape= JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    @JsonFormat(shape= JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
    private LocalDateTime inoculationTime;

2. @Deprecated

@Deprecated是java内置注解,此注解可以用在方法,属性,类上,表示不推荐程序员使用,但是还可以使用

3. @Min(value=1,“必须大于等于1”)

被注解的元素其值必须大于等于指定的值,并且类型为int,long,float,double。

4. @Max(value=3,“必须小于等于3”)

验证 Number 和 String 对象是否小等于指定的值,并且类型为int,long,float,double。

5. @Size(min=, max=)

验证对象(Array,Collection,Map,String)被注解的元素的长度必须在指定范围内,并且类型为String,Array,List,Map。

  @Size(min = 1, message = "至少要有一个属性")

6. @Length(min=, max=) 验证字符串长度是否在给定的范围之内

max和min是对你填的“数字”是否大于或小于指定值,这个“数字”可以是number或者string类型。长度限制用length。

7. @NotBlank(message = “联系人不能为空”)

判断该属性是否为null,“”

8. @NotNull(message = “商品单价不能为空”)

判断该属性是否为null

9. @NotEmpty(message = “商品列表不能为空”)

判断该属性是否为[]

10. Lombox注解

- @Data 自动生成get和set方法
- @ToString 重写toString
- @EqualsAndHashCode 可以使用字段为该类生成 Equals 和 HashCode 方法。
- @NoArgsConstructor 生成无参构造器
- @AllArgsConstructor 生成全参构造器
- @Slf4j 日志 log.

11. @Positive,整数 @PositiveOrZero,

整数或零

@PositiveOrZero(message = "排序要大于等于0")
private Integer sort;
@Positive(message = "数量要是整数")
private Integer sum;

12. @Digits

验证注解的元素值的整数位数和小数位数上限 ,并且类型为float,double,BigDecimal。

@Digits(integer = 12,fraction = 2,message = "整数位上限为12,小数位上限为2")

13. @Range注解

验证注解的元素值在最小值和最大值之间,并且类型为BigDecimal,BigInteger,CharSequence,byte,short,int,long。

@Range(min = 0,max = 100,message = "必须大于等于0,小于等于100")

在这里插入图片描述

14. @Length

注解 :验证注解的元素值长度在min和max区间内 ,并且类型为String。

@Length(min = 11, max = 11, message = "手机号只能为11位")

15. @DecimalMin注解 :

验证注解的元素值大于等于@DecimalMin指定的value值,并且类型为BigDecimal、BigInteger、double、float。

@DecimalMin(value = "0",message = "初始单价需要大于等于{value}")
@DecimalMin(value = "0",inclusive = false,message = "初始单价需要大于且不等于{value}")

16. @DecimalMax注解 :

验证注解的元素值小于等于@DecimalMax指定的value值 ,并且类型为BigDecimal、BigInteger、double、float。

@DecimalMax(value = "100",message = "初始单价需要小于等于{value}")
@DecimalMax(value = "100",inclusive = false,message = "初始单价需要小于且不等于{value}")

17. @Past注解 :

被注解的元素必须为过去的一个时间,并且类型为java.util.Date。

18. @Future注解 :

被注解的元素必须为未来的一个时间,并且类型为java.util.Date。

19. @AssertTrue注解 :

被注解的元素必须为true,并且类型为boolean。

20. @AssertFalse注解 :

被注解的元素必须为false,并且类型为boolean。

使用3~9注解前提是在Controller中添加:
@Validated@Valid
才会生效

21. @Pattern

匹配正则表达式

    @NotBlank(message = "手机号码不能为空")
    @Length(min = 11, max = 11, message = "手机号只能为11位")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
    private String phone;

常用正则表达式
数字

1、数字校验
@Pattern(regexp = "^[0-9]*$",message = "必须为数字")
^[0-9]*$
2、n位的数字

^\d{n}$
3、至少n位的数字

^\d{n,}$
4、m-n位的数字

^\d{m,n}$
5、零开头的数字

^(0|[1-9][0-9]*)$
6、非零开头的最多带两位小数的数字

^([1-9][0-9]*)+(.[0-9]{1,2})?$
7、正数、负数、和小数

^(\-|\+)?\d+(\.\d+)?$

8、有两位小数的正数值

^[0-9]+(.[0-9]{2})?$
9、非零的正整数

^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
10、非零的负整数

^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
11、非负整数

^\d+$ 或 ^[1-9]\d*|0$
12、非正整数

^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
13、非负浮点数

^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
14、非正浮点数

^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
15、正浮点数

^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
16、负浮点数

^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
17、浮点数

^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

字符串

1、汉字

^[\u4e00-\u9fa5]{0,}$
2、英文和数字

^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
3、长度为3-20的所有字符

^.{3,20}$
4、由26个英文字母组成的字符串

^[A-Za-z]+$
5、由26个大写英文字母组成的字符串

^[A-Z]+$
6、由26个小写英文字母组成的字符串

^[a-z]+$
7、由数字和26个英文字母组成的字符串

^[A-Za-z0-9]+$
8、由数字、26个英文字母或者下划线组成的字符串

^\w+$ 或 ^\w{3,20}$
9、中文、英文、数字包括下划线

^[\u4E00-\u9FA5A-Za-z0-9_]+$
10、可以输入含有^%&',;=?$\"等字符

[^%&',;=?$\x22]+
11、禁止输入含有~的字符:

[^~\x22]+

其他

1Email地址

^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2、域名

[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3InternetURL

[a-zA-z]+://[^\s]*^https://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4、手机号码

^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
5、电话号码

^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 
6、国内电话号码(0511-4405222021-87888822)

\d{3}-\d{8}|\d{4}-\d{7}
7、身份证号

1518位身份证:^\d{15}|\d{18}$
15位身份证:^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位身份证:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
8、短身份证号码(数字、字母x结尾)

^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
9、帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线)

^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10、密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)

^[a-zA-Z]\w{5,17}$
11、强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间)

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 
12、日期格式:

^\d{4}-\d{1,2}-\d{1,2}
13、一年的12个月(0109112)

^(0?[1-9]|1[0-2])$
14、中文字符的正则表达式

[\u4e00-\u9fa5]
15、空白行的正则表达式

\n\s*\r (可以用来删除空白行)
16HTML标记的正则表达式

<(\S*?)[^>]*>.*?|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
17、首尾空白字符的正则表达式

^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
18、腾讯QQ(腾讯QQ号从10000开始)

[1-9][0-9]{4,}
19、中国邮政编码(中国邮政编码为6位数字)

[1-9]\d{5}(?!\d)
20IP地址

\d+\.\d+\.\d+\.\d+ 

这里需要统一处理一下validation的错误信息

@RestControllerAdvice
@Order(1)
public class ParamCheckExceptionHandler {
    /**
     * 校验错误拦截处理
     *
     * @param exception MethodArgumentNotValidException错误类
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result validationBodyException(MethodArgumentNotValidException exception) {

        BindingResult result = exception.getBindingResult();

        //返回第一个错误
        String errMsg = result.getAllErrors().get(0).getDefaultMessage();

        return Result.fail(errMsg);
    }
}

2 常用注解

1. @Transactional 事务注解

@Transactional(rollbackFor = Exception.class)

2. @ComponentScan 指定组件扫描包的位置

@ComponentScan(basePackages = {"com.ssy.lingxi"})

3. @EntityScan 扫描和发现指定包及其子包中的Entity定义

@EntityScan(basePackages = {"com.ssy.lingxi.member.merchant.entity"})

4. EnableJpaRepositories 用来扫描和发现指定包及其子包中的Repository定义。

@EnableJpaRepositories(basePackages = {"com.ssy.lingxi.member.repositories","come.ssy.lingxi.member.repositories"})

5. @EnableFeignClients 启用feign客户端,且可以指定包

@EnableFeignClients(basePackages = {"com.ssy.lingxi.order.api.feign", "com.ssy.lingxi.workflow.api.feign", "com.ssy.lingxi.sms.api.feign", "com.ssy.lingxi.pay.api.feign", "com.ssy.lingxi.order.api.feign", "com.ssy.lingxi.platform.manage.api.feign", "com.ssy.lingxi.report.api.feign", "com.ssy.lingxi.message.api.feign", "com.ssy.lingxi.product.api.feign", "com.ssy.lingxi.search.api.feign","com.ssy.lingxi.platform.template.api.feign.inner", "com.ssy.lingxi.scheduler.api.feign","com.ssy.lingxi.feign"})

6. @Autowired 只按照byType注入

如果需要按照name注入,需要配合@Qualifier(“bookDao”),指定name来使用即可

7. @Resource 先自动按照byName方式注入

@Resource装配顺序:

(1)如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

(2)如果指定了name,则从Spring上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

(3)如果指定了type,则从Spring上下文中找到类型匹配的唯一bean进行装配,找不到或找到多个,都抛出异常

(4)如果既没指定name,也没指定type,则自动按照byName方式进行装配。如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入。

3 @Valid和@Validated

  • @Valid是使用Hibernate validation的时候使用
    标准JSR-303规范的标记型注解,用来标记验证属性和方法返回值,进行级联和递归校验

  • @Validated是只用Spring Validator校验机制使用@Validation对@Valid进行了二次封装,在使用上并没有区别,但在分组、注解位置、嵌套验证等功能上有所不同
    Spring的注解,是标准JSR-303的一个变种(补充),提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

方法级别:
@Validated注解可以用于类级别,用于支持Spring进行方法级别的参数校验。@Valid可以用在属性级别约束,用来表示级联校验。
@Validated只能用在类、方法和参数上,而@Valid可用于方法、字段、构造器和参数上

3.1 嵌套验证

注意:如果存在嵌套验证可以在入参添加@Validated,在需要验证的属性上添加@Valid,即可实现嵌套验证

那么何为嵌套验证
这里有个ClassGrade班级的实体类:

@Data
public class ClassGrade{
 
  @NotNull(message = "id不能为空")
  @Min(value = 1, message = "id必须为大于0")
  private Long id;
 
  @NotNull(message = "props不能为空")
  @Size(min = 1, message = "至少要有一个属性")
  @Valid
  private List<Student> students;
}

班级里有很多学生Student带有很多属性:

@Data
public class Student{
 
  @NotNull(message = "id不能为空")
  @Min(value = 1, message = "id必须为大于0")
  private Long id;
  
  @NotBlank(message = "name不能为空")
  private String name;
  
  @NotNull(message = "age不能为空")
  private Integer age;
  
  @NotBlank(message = "adderss不能为空")
  private String adderss;
  
}

学生Student这个实体也有自己的验证机制name不能为空,id必须为大于0等
controller必须加@Valid,嵌套验证才会生效

@RestController("/user")
public class ItemController {
 
  @PostMapping("/class/add")
  public void addItem(@RequestBody @Valid @Validated ClassGrade classGrade) {
    doSomething();
  }
}

如果ClassGrade实体类中的students属性不额外加注释,只有@NotNull和@Size,无论入参采用@Validated还是@Valid验证,Spring Validation框架只会对ClassGrade的id和students做非空和数量验证,不会对students字段里的Student实体进行字段验证,也就是@Validated和@Valid加在方法参数前,都不会自动对参数进行嵌套验证。也就是说如果传的List<Student>中的id为空或者是负数,入参验证不会检测出来。

为了能够进行嵌套验证,必须手动在ClassGrade实体的students字段上明确指出这个字段里面的实体也要进行验证。由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能,那么我们能够推断出:@Valid加在方法参数时并不能够自动进行嵌套验证,而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated或@Valid来进行嵌套验证。

因此在Controller中的参数添加@Validated注解,并且ClassGrade实体类中的students属性上添加@Valid注解
,这里在Controller中已经添加,所以在Student中添加@Valid注解即可实现嵌套验证

@Data
public class ClassGrade{
 
  @NotNull(message = "id不能为空")
  @Min(value = 1, message = "id必须为大于0")
  private Long id;
 
  @Valid// 嵌套验证必须用@Valid
  @NotNull(message = "props不能为空")
  @Size(min = 1, message = "至少要有一个属性")
  private List<Student> students;
}

3.2 分组

    /**
     * id
     */
    @ApiModelProperty("id")
    @NotNull(message = "id不能为空",groups = {Update.class, Delete.class})
    private Long id;

    /**
     * 分类名字
     */
    @ApiModelProperty("分类名字")
    @NotBlank(message = "分类名字不能为空", groups = {Insert.class, Update.class})
    private String name;

    /**
     * 父分类id
     */
    @ApiModelProperty("父分类id")
    @NotNull(message = "父分类id不能为空", groups = {Insert.class})
    @Min(value = 1, message = "父分类id需要大于0", groups = {Insert.class, Update.class})
    private Long parentId;
    
    private class Insert {
    }
    private class Update {
    }
    
    /**
     * 新增代码分类
     * @param request 请求参数
     * @return 结果
     */
    @ApiOperation(value = "新增代码分类", notes = "新增代码分类", httpMethod = "POST")
    @PostMapping("/add")
    public Wrapper add(@RequestBody @Validated(Insert.class) StandardCodeCategoryRequest request) {
        codeCategoryService.add(request);
        return Wrapper.success();
    }

    /**
     * 修改代码分类
     * @param request 请求参数
     * @return 结果
     */
    @ApiOperation(value = "修改代码分类", notes = "修改代码分类", httpMethod = "POST")
    @PostMapping("/update")
    public Wrapper update(@RequestBody @Validated(Update.class) StandardCodeCategoryRequest request) {
        codeCategoryService.update(request);
        return Wrapper.success();
    }

    @PostMapping("/addOrUpdate")
    public Wrapper addOrUpdate(@RequestBody TestEntity testEntity) {
        System.out.println("testEntity = " + testEntity.toString());
        ValidatorUtil.validateParam(testEntity, Insert.class);

        return Wrapper.success();
    }

4 枚举

/**
 * 交易类型枚举
 * @version 1.0.0
 * @date 2022/12/28
 */
public enum TransactionTypeEnum {
    /**
     * 支付宝支付 - 1
     */
    ALIPAY_PAY(1, "支付宝支付"),

    /**
     * 微信支付 - 2
     */
    WECHAT_PAY(2, "微信支付"),

    /**
     * 银行卡支付 - 3
     */
    UNION_PAY(3, "银行卡支付"),

    /**
     * B2B线上支付 - 4
     */
    B2B_ONLINE_PAY(4, "B2B线上支付"),

    /**
     * 线下支付 - 5
     */
    OFFLINE_PAY(5, "线下支付");

    TransactionTypeEnum(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

    /**
     * 类型枚举值
     */
    private Integer code;

    /**
     * 类型名称
     */
    private String name;

    public Integer getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    /**
     * 根据枚举值获得名称
     * @param code 类型枚举值
     * @return 类型名称
     */
    public static String getNameByCode(Integer code) {
        TransactionTypeEnum typeEnum = Arrays.stream(TransactionTypeEnum.values()).filter(e -> e.getCode().equals(code)).findFirst().orElse(null);
        return typeEnum == null ? "未知" : typeEnum.getName();
    }

    /**
     * 获取枚举所有id
     */
    public static List<Integer> toList() {
        return Arrays.stream(TransactionTypeEnum.values()).map(TransactionTypeEnum::getCode).collect(Collectors.toList());
    }
     /**
     * 获取所有id和name
     */
        public static List<DropdownItem> toDropdownList() {
        return Arrays.stream(TransactionTypeEnum.values()).sorted(Comparator.comparingInt(TransactionTypeEnum::getCode)).map(e -> new DropdownItem(e.getCode(), e.getName())).collect(Collectors.toList());
    }
}

DropdownItem

/**
 * 下拉框内容返回VO
 * @version 2.0.0
 * @date 2020-07-14
 */
@Data
public class DropdownItem implements Serializable {

    public DropdownItem() {
    }

    public DropdownItem(Integer id, String text) {
        this.id = id;
        this.text = text;
    }

    /**
     * 下拉选择框的id
     */
    private Integer id;

    /**
     * 下拉选择框的文本内容
     */
    private String text;
}

通常情况下用枚举判断,名称可能会常变化,但枚举较少

5 @PostConstruct

@PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。

@SpringBootApplication
@ComponentScan(basePackages = {"com.my.spider"})
@MapperScan("com.my.spider.mapper")
public class MySpiderApplication {
    @Autowired
    private SpiderHandle spiderHandle;
    @Autowired
    private ContentNoticeHandle contentNoticeHandle;

    public static void main(String[] args) {
        SpringApplication.run(MySpiderApplication.class, args);
    }

    @PostConstruct
    public void task(){
        contentNoticeHandle.spiderData();
    }/*
    @PostConstruct
    public void task(){
        spiderHandle.spiderData();
    }
*/
}

6 java基础-移位运算符

6.1 带符号左移运算符<<

左移 << 正数左移低位补零,负数左移高位舍弃低位补零

  1. 正数例:6<<2
    表示将6变为2进制数字后整体左移2位,6的二进制数表示:110,左移两位变为:11000,左移后十进制数为24+23=16+8=24 其实左移快捷简单的算法可以理解为

在这里插入图片描述

负数例:-6<<2
表示将-6变为2进制数字后整体左移2位,-6的二进制数表示:11111111111111111111111111111010,计算6的负数二进制 = 6的二进制110取反得(111111111111111[符号位补1,符号位+数值位的总位数32位])001,然后加一得(11111111111111111111111111111)010,左移两位变为:(111111111111111111111111111)01000【高位舍弃,低位补零,然后取反+1,即10111(取反)+00001=11000(补码)】,左移后十进制数为 -(24+23)=-(16+8)=-24,其实左移快捷简单的算法可以理解为

在这里插入图片描述

注意:符号位不参与移位,负数以补码的形式表示,正数的补码和原码一样,负数的补码由去掉符号位的原码(该数的绝对值)的反码再加一可得

6.2 带符号右移运算符>>

带符号右移 >> 正数右移高位补0,负数右移高位补1

  1. 正数例:6>>2
    表示将6变为2进制数字后整体右移2位,6的二进制数表示:00110,右移两位变为:00001,右移后十进制数为20=1,其实右移快捷简单的算法可以理解为

在这里插入图片描述

  1. 负数例:-6>>2
    表示将-6变为2进制数字后整体右移2位,-6的二进制数表示:11111111111111111111111111111010,右移两位变为:11111111111111111111111111111110【高位补1,然后取反+1,即001(取反)+001=010(补码)】,右移后十进制数为-21=-2,其实右移快捷简单的算法可以理解为
    在这里插入图片描述

6.3 无符号右移 >>>

无符号右移 >>> 无论是正数还是负数,高位通通补0

  1. 正数例:6>>>2,与带符号右移(6>>2)一样,无差别。
  2. 负数例:-6>>>2
    表示将-6变为2进制数字后整体右移2位,-6的二进制数表示:11111111111111111111111111111010,无符号右移两位变为:00111111111111111111111111111110【高位补0】,无符号右移十进制数为 :
    在这里插入图片描述

7 java加锁

  1. 减少锁的持有时间
  2. 将大对象,拆成小对象,大大增加并行度,降低锁竞争。如此一来偏向锁,轻量级锁成功率提高.。

7.1 Lock

使用方法:多线程下访问(互斥)共享资源时, 访问前加锁,访问结束以后解锁.

// 创建可重入锁
private static final Lock lock = new ReentrantLock();
  lock.lock();  
  try{
          代码块;
  }finally{
  		 // 释放锁
         lock.unlock();
  }

7.2 synchronized

  1. 减少锁的持有时间
    例如避免给整个方法加锁。
public synchronized void syncMethod(){ 
    othercode1(); 
    mutextMethod(); 
    othercode2(); 
}

改进后

public void syncMethod2(){
    othercode1();
    synchronized(this){
        mutextMethod();
    }
    othercode2();
}
  1. 将大对象,拆成小对象,大大增加并行度,降低锁竞争。如此一来偏向锁,轻量级锁成功率提高.。

一个简单的例子就是 jdk 内置的 ConcurrentHashMap 与 SynchronizedMap。

Collections.synchronizedMap 其本质是在读写 map 操作上都加了锁,在高并发下性能一般。

7.3 数据库加锁

使用数据库的悲观锁for update,在 sql后面加上

for update

在sql语句后加 for update就加上了锁,在查询的时候进行加锁,在加锁后不能进行查询。提交时候后其他人才能查询。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值