多线程中出现数据安全隐患的原因
多线程程序 共享资源(成员变量) 多条语句操作共享资源
多线程代码创建方式
1.继承Thread
2.实现Runnable接口
多线程安全问题是如何出现的?
常见情况是由于线程的随机性+访问延迟。
以后如何判断程序有没有线程安全问题?
在多线程程序中 + 有共享数据 + 多条语句操作共享数据
注解
-
JDK自带注解
@Override :用来标识重写方法 -
元注解
@Target 注解用在哪里:类上、方法上、属性上等等
@Retention 注解的生命周期:源文件中、字节码文件中、运行中 -
自定义注解
注意:注解的语法写法和常规java的语法写法不同
自定义注解
1.首先注意:自定义注解的语法与java不同,不要套用java的格式
2.注解定义要使用“@interface 注释名”的方式来定义
3.使用注解时,只要在指定的自定义注解名字前加上“@”即可使用此注解
4.自定义注解还可以添加功能—给注解添加属性
int age();不是方法的定义。而是给自定义注解中定义age属性的语法
如果为了使用注解是方便,还可以给属性指定默认值,这样就可以直接使用,格式:int age() default 0
5.注解中还可以添加功能 ,可以定义特殊属性value
特殊属性的定义方式与别的属性相同,主要是使用方式不同
使用次此注解给属性赋值的时候,可以不用写成"@Test(value = “Apple”)"
格式可以简化“@Test("Apple)”直接写值
但是自定义以简写,如果自定义了默认值,可以不用赋值,直接使用
自定义注解
通过@Target注解表示次自定义注解可以使用的位置
注意:@Target注解使用时需要导包,我们通过“ElementType.静态常量值”的方式来指定
此自定义注解可以使用的位置
如果有多个值,可以使用"{,}"的格式来写
通过@Retention注解表示自定义注解的生命周期
注意:@retention使用时也需要导包,通过RetentionPolicy.静态常量值来指定此自定义注解的生命周期
也就是指自定义注解可以存在在哪个文件中:源文件中/字节码文件中/运行时有效
而且这三个值,只能三选一,不能同时写多个
结论
1.自定义注解能够加在什么位置,取决于@Test注解的值
2.注解@Test可以存在于多个位置,如果@Target有多个值,格式是{ , }
原因:Target注解的源码ElementType[] value();
3.当注解没有定义属性时,可以直接使用,如果有属性了,就需要给属性赋值
4.给属性赋值的格式“@Test(age = 10)”,注意,不能直接写10,这是错误格式
5.给age属性赋予默认值后,可以不加属性值,直接使用注解,此时使用的就是age的默认值
6.给age属性赋予默认值时可以简写,相当于,相当于value=“apple”
7.因为已有默认值,所以不用给特殊属性赋值,直接使用@Test
public class TestAnntqtion { }
/*通过@Target注解表示次自定义注解可以使用的位置
* 注意:@Target注解使用时需要导包,我们通过“ElementType.静态常量值”的方式来指定
* 此自定义注解可以使用的位置
* 如果有多个值,可以使用"{,}"的格式来写*/
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE,ElementType.FIELD})//表示此注解可以加在方法上
/*通过@Retention注解表示自定义注解的生命周期
* 注意:@retention使用时也需要导包,通过RetentionPolicy.静态常量值来指定此自定义注解的生命周期
* 也就是指自定义注解可以存在在哪个文件中:源文件中/字节码文件中/运行时有效
* 而且这三个值,只能三选一,不能同时写多个*/
@Retention(RetentionPolicy.SOURCE)
/*0.首先注意:自定义注解的语法与java不同,不要套用java的格式*/
/*1.注解定义要使用“@interface 注释名”的方式来定义*/
@interface Test{
/*3.自定义注解还可以添加功能---给注解添加属性
* int age();不是方法的定义。而是给自定义注解中定义age属性的语法
* 如果为了使用注解是方便,还可以给属性指定默认值,这样就可以直接使用,格式:int age() default 0*/
int age() default 0;
/*4.注解中还可以添加功能 ,可以定义特殊属性value
* 特殊属性的定义方式与别的属性相同,主要是使用方式不同
* 使用次此注解给属性赋值的时候,可以不用写成"@Test(value = "Apple")"
* 格式可以简化“@Test("Apple)”直接写值
* 但是自定义以简写,如果自定义了默认值,可以不用赋值,直接使用*/
}
/*2.使用注解时,只要在指定的自定义注解名字前加上“@”即可使用此注解*/
//@Test
class TestAnno{
/*分别给类 属性 方法都添加@Test注解都添加了@Test注解,只要方法上不报错
* 结论:自定义注解能够加在什么位置,取决于@Test注解的值*/
/*修改@Test注解的值:@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE,ElementType.FIELD})
* 结论:注解@Test可以存在于多个位置,如果@Target有多个值,格式是{ , }
* 原因:Target注解的源码ElementType[] value();*/
//@Test
String name;
/*
* 测试3:当我们添加了注解的age属性时,@Test注解报错
* 结论:当注解没有定义属性时,可以直接使用,如果有属性了,就需要给属性赋值
* 测试4;给@Test注解的age属性赋值以后,就不报错了
* 结论:给属性赋值的格式“@Test(age = 10)”,注意,不能直接写10,这是错误格式
* 测试5:给age属性赋予默认值后,可以不加属性值,直接使用注解,此时使用的就是age的默认值*/
/*测试6:给age属性赋予默认值时可以简写,相当于,相当于value="apple"*/
/*测试7:因为已有默认值,所以不用给特殊属性赋值,直接使用@Test*/
@Test(age = 10)
public void eat(){
System.out.println("干饭");
}
}