同步方法解决线程安全性问题
普通同步方法
import com.itheima.tikets.Student;
public class TicketsThread extends Thread {
//100 张票 三个窗口售票
//每一个窗口都有100张票 还是 三个窗口共同出售 100张票
//被static修饰的属性的特点 只有一份 被所有的对象共享
private static int tickets = 100;
//锁对象的条件 被所有的线程共享 是一个惟一的
private static Student stu = new Student();
@Override
public void run() {
while(true){
sell();
if(tickets <= 0){
break;
}
}
}
//普通同步方法 -- 无法解决
// public synchronized void sell(){
//锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
// if (tickets > 0) {
// System.out.println(getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
//静态同步方法可以解决线程安全性问题?
public static synchronized void sell(){
//锁对象 -- 当前类的字节码对象 TicketsThread.class 唯一的 被所有的线程共享
//锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
public class Demo {
public static void main(String[] args) {
TicketsThread t1 = new TicketsThread();
t1.setName("ww");
TicketsThread t2 = new TicketsThread();
t2.setName("yy");
TicketsThread t3 = new TicketsThread();
t3.setName("zz");
t1.start();
t2.start();
t3.start();
}
}
静态同步方法
public class TicketsThread implements Runnable {
//100 张票 三个窗口售票
//每一个窗口都有100张票 还是 三个窗口共同出售 100张票
//被static修饰的属性的特点 只有一份 被所有的对象共享
private static int tickets = 100;
//锁对象的条件 被所有的线程共享 是一个惟一的
private static Student stu = new Student();
@Override
public void run() {
while(true){
sell();
if(tickets <= 0){
break;
}
}
}
//普通同步方法 -- 无法解决
// public synchronized void sell(){
// //锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
// if (tickets > 0) {
// System.out.println(getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
//静态同步方法可以解决线程安全性问题?
public static synchronized void sell(){
//锁对象 -- 当前类的字节码对象 TicketsThread.class 唯一的 被所有的线程共享
//锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
public class TicketsDemo {
public static void main(String[] args) {
//因为runnable实现类对象只创建了一次 tickets 值被初始化一次 被三个线程所共享
TicketsThread ticketsThread = new TicketsThread();
//创建售票窗口 线程
Thread t1 = new Thread(ticketsThread);
Thread t2 = new Thread(ticketsThread);
Thread t3 = new Thread(ticketsThread);
t1.setName("ww");
t2.setName(yy");
t3.setName("zz");
t1.start();
t2.start();
t3.start();
}
}
总结:
普通同步方法
解决实现Runnable这种方式 安全性问题
静态同步方法
解决继承 以及 实现 这两种方式的 安全性问题
properties
具备map的功能
增put删remove改put查get
特有的功能 -- 只能操作 String类型
public class PropertiesDemo_02 {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("itheima001","WW");
properties.setProperty("itheima002","YY");
properties.setProperty("itheima003","ZZ");
for (String key : properties.stringPropertyNames()) {
System.out.println(key + "---" + properties.getProperty(key));
}
}
}
反射
反射的前提是获取字节码对象
三种方式
1、对象.getClass();
2、类名.class
3、Class.forName(String className)
使用反射操作所有构造方法
public class RelectDemo_02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.获取字节码对象
Class<?> clazz = Class.forName("com.itheima.reflect_02.Student");
//2.获取私有的构造方法
// Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
// for (Constructor<?> declaredConstructor : declaredConstructors) {
// System.out.println(declaredConstructor);
// }
//Class<?>... parameterTypes 构造方法参数列表的数据类型
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class);
//3.使用私有的构造方法创建对象
//Object ... initargs 参数的值
//IllegalAccessException 当使用反射创建对象 或者 调用方法 属性 当前 这些构造 方法 属性 不可以调用的时候
Object obj = declaredConstructor.newInstance("岳父大人");
System.out.println(obj);
}
}
使用反射操作所有的方法
-
获取字节码对象
-
创建对象
-
获取私有的方法
-
暴力访问
-
调用方法
public class MethodReflectDemo_02 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1. 获取字节码对象
Class<?> clazz = Class.forName("com.itheima.method.Student");
//2. 创建对象
Object obj = clazz.newInstance();
//3. 获取私有的方法
//String name, 方法名
// Class<?>... parameterTypes 参数列表对应的类型
Method showMethod = clazz.getDeclaredMethod("show", String.class);
//4. 暴力访问
showMethod.setAccessible(true);
//5. 调用方法
//Object obj, 调用的是哪一个对象的方法
// Object... args 方法对应的参数
showMethod.invoke(obj, "兰兰");
//InvocationTargetException 当我们调用的方法 构造方法中出现异常的时候 抛出这个异常
}
}
BeanUtils(populate方法)
public class BeanUtils {
private BeanUtils(){}
public static void setProperty(Object obj,String fieldName,Object value) throws Exception {
//向student对象中赋值操作
Class<?> clazz = obj.getClass();
Field declaredField = clazz.getDeclaredField(fieldName);
declaredField.setAccessible(true);
declaredField.set(obj,value);
}
//使用方法进行赋值操作
public static void setProperty2(Object obj,String fieldName,Object value) throws Exception{
//获取字节码对象
Class<?> clazz = obj.getClass();
//获取方法进行赋值操作
fieldName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1,fieldName.length());
//获取所有的公共的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//method.getName() 获取方法名字
if(fieldName.equals(method.getName())){
method.invoke(obj,value);
}
}
}
public static Object getProperty(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
Field declaredField = clazz.getDeclaredField(name);
//暴力访问
declaredField.setAccessible(true);
Object value = declaredField.get(obj);
return value;
}
public static void populate(Object obj,Map<String,Object> map) throws Exception{
Class<?> clazz = obj.getClass();
for (String key : map.keySet()) {
//将value写入到属性中
//key -- 属性名 value -- 属性值
//获取 属性对象
//获取 key(属性名) 对应的字段
Field keyField = clazz.getDeclaredField(key);
//进行赋值操作
keyField.setAccessible(true);
keyField.set(obj,map.get(key));
}
}
}
public class Demo {
public static void main(String[] args) throws Exception {
Student student = new Student();
//给哪一个属性赋值 赋什么值
BeanUtils.setProperty2(student,"name","lisa");
BeanUtils.setProperty2(student,"age",39);
System.out.println(student);
Object name = BeanUtils.getProperty(student, "name");
System.out.println(name);
System.out.println("--------------------------------");
Map<String,Object> map = new HashMap<>();
map.put("name","lisa");
map.put("age",39);
map.put("address","阜阳");
map.put("id",111);
//将集合中的内容 直接 写入到对象当中
Student student1 = new Student();
BeanUtils.populate(student1,map);
System.out.println(student1);
}
}
动态代理
Spring -- IOC AOP
IOC -- 控制反转
AOP -- 面向切面
OOP -- 面向对象
简单来讲 -- AOP 可以在不修改源码的情况下,增强某个功能
两种方案 :
其中一种 JDK提供的 动态代理 面像接口
Proxy
//1.创建一个接口 将需要准备增强的方法 抽取到接口中让 被代理对象 实现这个接口
public interface Star {
public void sing(double money);
public void jump(double money);
public void rap(double money);
public void basketball(double money);
public void jiUSoBeautiful();
}
import java.sql.Statement;
public class CaiXuKun implements Star{
public void sing(double money){
System.out.println("给了" +money + "唱了一首歌曲" );
}
public void jump(double money){
System.out.println("给了" +money + "跳起来了");
}
public void rap(double money){
System.out.println("给了" +money + "唱了一首rap");
}
public void basketball(double money){
System.out.println("给了" +money + "跳了一会篮球");
}
public void jiUSoBeautiful(){
System.out.println("ye~~~~");
}
public void sleep(){
System.out.println("欧ye,sleep 了");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
CaiXuKun cxk = new CaiXuKun();
//1.创建一个接口 将需要准备增强的方法 抽取到接口中
//让 被代理对象 实现这个接口
//Proxy
//ClassLoader loader,Class<?>[] interfaces,InvocationHandler h
//loader 类加载器 -- 代理对象对应的类加载器
ClassLoader classLoader = cxk.getClass().getClassLoader();
//interfaces 代理对象 实现的所有的接口
Class<?>[] interfaces = cxk.getClass().getInterfaces();
//InvocationHandler 接口
Star proxyObject = (Star) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
/*
proxy 代理对象 proxyObject
*method 方法 代理对象所调用的方法
*args 参数 调用方法的时候 需要传递对应的参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//不要使用 proxy 调用方法
//StackOverflowError
//proxy.toString();
String name = method.getName();
Object invoke = null;
if("sing".equals(name)){
invoke = method.invoke(cxk, args);
}else{
System.out.println("签合同");
System.out.println("给钱");
invoke = method.invoke(cxk, args);
//返回值 动态代理调用的方法的返回值
System.out.println("合理避税");
System.out.println("打一顿....");
}
return invoke;
}
});
proxyObject.sing(1000);
proxyObject.basketball(2000);
proxyObject.rap(2000);
proxyObject.jiUSoBeautiful();
}
}