注解大全
- 1 实体类校验注解
- 1. 时间
- (1) @DateTimeFormat(pattern = "yyyy-MM-dd")
- (2) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
- 2. @Deprecated
- 3. @Min(value=1,"必须大于等于1")
- 4. @Max(value=3,"必须小于等于3")
- 5. @Size(min=, max=)
- 6. @Length(min=, max=) 验证字符串长度是否在给定的范围之内
- 7. @NotBlank(message = "联系人不能为空")
- 8. @NotNull(message = "商品单价不能为空")
- 9. @NotEmpty(message = "商品列表不能为空")
- 10. Lombox注解
- 11. @Positive,整数 @PositiveOrZero,
- 12. @Digits
- 13. @Range注解
- 14. @Length
- 15. @DecimalMin注解 :
- 16. @DecimalMax注解 :
- 17. @Past注解 :
- 18. @Future注解 :
- 19. @AssertTrue注解 :
- 20. @AssertFalse注解 :
- 21. @Pattern
- 2 常用注解
- 1. @Transactional 事务注解
- 2. @ComponentScan 指定组件扫描包的位置
- 3. @EntityScan 扫描和发现指定包及其子包中的Entity定义
- 4. EnableJpaRepositories 用来扫描和发现指定包及其子包中的Repository定义。
- 5. @EnableFeignClients 启用feign客户端,且可以指定包
- 6. @Autowired 只按照byType注入
- 7. @Resource 先自动按照byName方式注入
- 3 @Valid和@Validated
- 3.1 嵌套验证
- 3.2 分组
- 4 枚举
- 5 @PostConstruct
- 6 java基础-移位运算符
- 6.1 带符号左移运算符<<
- 6.2 带符号右移运算符>>
- 6.3 无符号右移 >>>
- 7 java加锁
- 7.1 Lock
- 7.2 synchronized
- 7.3 数据库加锁
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。
@DecimalMin(value = "0",message = "初始单价需要大于等于{value}")
16. @DecimalMax注解 :
验证注解的元素值小于等于@DecimalMax指定的value值 ,并且类型为BigDecimal。
@DecimalMax(value = "100",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]+
其他
1、Email地址
^\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})+/.?
3、InternetURL
[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-4405222、021-87888822)
\d{3}-\d{8}|\d{4}-\d{7}
7、身份证号
15或18位身份证:^\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个月(01~09和1~12)
^(0?[1-9]|1[0-2])$
14、中文字符的正则表达式
[\u4e00-\u9fa5]
15、空白行的正则表达式
\n\s*\r (可以用来删除空白行)
16、HTML标记的正则表达式
<(\S*?)[^>]*>.*?|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
17、首尾空白字符的正则表达式
^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
18、腾讯QQ号(腾讯QQ号从10000开始)
[1-9][0-9]{4,}
19、中国邮政编码(中国邮政编码为6位数字)
[1-9]\d{5}(?!\d)
20、IP地址
\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 带符号左移运算符<<
左移 << 正数左移低位补零,负数左移高位舍弃低位补零
- 正数例: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
- 正数例:6>>2
表示将6变为2进制数字后整体右移2位,6的二进制数表示:00110,右移两位变为:00001,右移后十进制数为20=1,其实右移快捷简单的算法可以理解为
- 负数例:-6>>2
表示将-6变为2进制数字后整体右移2位,-6的二进制数表示:11111111111111111111111111111010,右移两位变为:11111111111111111111111111111110【高位补1,然后取反+1,即001(取反)+001=010(补码)】,右移后十进制数为-21=-2,其实右移快捷简单的算法可以理解为
6.3 无符号右移 >>>
无符号右移 >>> 无论是正数还是负数,高位通通补0
- 正数例:6>>>2,与带符号右移(6>>2)一样,无差别。
- 负数例:-6>>>2
表示将-6变为2进制数字后整体右移2位,-6的二进制数表示:11111111111111111111111111111010,无符号右移两位变为:00111111111111111111111111111110【高位补0】,无符号右移十进制数为 :
7 java加锁
- 减少锁的持有时间
- 将大对象,拆成小对象,大大增加并行度,降低锁竞争。如此一来偏向锁,轻量级锁成功率提高.。
7.1 Lock
使用方法:多线程下访问(互斥)共享资源时, 访问前加锁,访问结束以后解锁.
// 创建可重入锁
private static final Lock lock = new ReentrantLock();
lock.lock();
try{
代码块;
}finally{
// 释放锁
lock.unlock();
}
7.2 synchronized
- 减少锁的持有时间
例如避免给整个方法加锁。
public synchronized void syncMethod(){
othercode1();
mutextMethod();
othercode2();
}
改进后
public void syncMethod2(){
othercode1();
synchronized(this){
mutextMethod();
}
othercode2();
}
- 将大对象,拆成小对象,大大增加并行度,降低锁竞争。如此一来偏向锁,轻量级锁成功率提高.。
一个简单的例子就是 jdk 内置的 ConcurrentHashMap 与 SynchronizedMap。
Collections.synchronizedMap 其本质是在读写 map 操作上都加了锁,在高并发下性能一般。
7.3 数据库加锁
使用数据库的悲观锁for update,在 sql后面加上
for update
在sql语句后加 for update就加上了锁,在查询的时候进行加锁,在加锁后不能进行查询。提交时候后其他人才能查询。