Java反射机制和线程

JAVA反射机制

已经加载过这个类,通过类名来找到这个类的所有相关信息。

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的成员变量和方法
  • 生成动态代理

反射相关的主要API:

  • java.lang.Class : 代表一个类
  • java.lang.reflect.Method : 代表类的方法
  • java.lang.reflect.Field : 代表类的成员变量
  • java.lang.flect.Constructor : 代表类的构造方法
// 获取Class对象
Class clazz = p.getClass();  // clazz里面包含了对象p所属类的有关信息
Class c1 = Person.class;  //  通过类名.class创建指定类的Class实例
Class c2 = Class.forName("包名.类名");  // 这个比较常用

// 获取
clazz.getName(); // 获取名称
clazz.getModifiers();  // 获取修饰符
Class[] paramClazz = clazz.getParameterTypes();  // 获取参数类型
Class superClazz = clazz.getSuperClass();  // 获取父类
Class[] interfaces = clazz.getInterfaces();  // 获取接口
Constructor[] cons = clazz.getConstructors();  // 获取public构造方法
Constructor[] cons = clazz.getDeclaredConstructors();  // 获取所有构造方法

// 动态调用构造器,创建对象,得到的都是Object,需要强制转换
Object obj = clazz.newInstance(); // 调用无参构造
Constructor con = clazz.getConstructor(String.class);
//获得参数为String的构造器。用DeclaredConstructors()可以获取private的构造方法。但是要在前面加一句,con.setAccessible(true); 解封装
Object obj = con.newInstance("lzq");  // 调用有参构造

// 动态获取方法、属性进行操作. 对私有属性、方法操作是,注意解封装
Method[] ms = clazz.getMethods();  // 获得全部公有方法,要获得私有的和上同理。
Field[] fs = clazz.getFiedls();  // 获取属性
Package p = clazz.getPackage();  //  获取包名
// 得到名称叫name 参数是String String 的方法。
Method m1 = clazz.getMethod("name",String.class,String.class);  
m1.invoke(obj, args);  // 参数1是需要实例化的对象,通过前面的构造可以得到,参数2是可变长的前面方法的实际参数,如果调用的方法有返回值,就接受并强制类型转换。
Field f = clazz.getFiedl("属性名");
f.set(stu, "aaaa");  // 设置stu对象的f属性值为aaaa
f.get(stu);  // 获取stu对象的f属性值,接收时注意类型转换。

// java 动态代理。注意 一个对象想要被代理,一定要有接口。
class ProxyOfTest implements InvocationHandler{
    Object obj;  // 被代理的对象
    public ProxyOfTest(Object obj){
        this.obj = obj;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable{
        // 此处 在指定方法调用前,动态添加行为
        Object result = method.invoke(this.obj, args); //执行的是代理对象的制定方法。
        // 此处 在指定方法调用后,动态添加行为
        return result;
    }
}
InvocationHandler handler = new ProxyOfTest(test); //对test对象进行代理,得到代理对象hander
Test t = (Test)Proxy.newProxyInstance(handler.getClass().getClassLoader(), test.getClass().getInterfaces(), handler);  // 返回的是Object类型,是成功代理后的对象。
t.test(); 

Java线程

Java.lang.Thread类

  • run()
  • start()
/*创建线程*/
class TestThread extends Thread{ //继承Thread类的方式创建多线程
    @Override
    public void run() {
        //  多线程运行的代码
    }
}
Thread t0 = new TestThread();
t0.start();  // 启动线程,运行run方法,是异步执行


class TestRunnable implements Runnable{ // 实现Runnable接口
    @Override
    public void run() {
        //  多线程运行的代码
    }
}
Thread t1 = new Thread(new TestRunnable());
Thread t2 = new Thread(new TestRunnable(), "t2");// 也可以通过这个方式,第二个参数是线程名称。
t1.start();  

使用Runnable接口实现,避免了单继承的局限性,使得多个线程可以共享一个接口实现对象,处理同一份资源。

一些常用的方法:

String name = t.getName();  // 返回线程的名称 默认为Thread-0,Threa-1等
t.setName("name");  // 设置线程名称 
/*线程优先级:1-10; 数字越大越高,默认为5*/
int t.getPriority();
t.setPriority(int);
Thread.yeild();  // 线程让步:暂停自己的执行,把执行机会让给别的线程
Thread.sleep(1000);  // 当前线程睡眠1000ms。
t.join(); // 相当于把t的run方法插入到这个位置。阻塞了当前的main方法,先执行join进来的线程的代码
t.stop(); // 强制停止
boolean t.isAlive();  // 判断当前线程是否还活着。

线程同步

  • 使用同一个同步锁的才能实现线程同步。

  • 在public方法上加上关键字 synchronized 同步锁。锁的是某个对象不是仅仅某个方法。不同的对象是不同的同步锁。

  • 在static方法上加synchronized 同步锁。所有的实例化对象都是同一个同步锁。

  • 用 synchronized(this){ } 来锁某个代码块。如果在其他方法中也有synchronized(this)锁住的代码块,它们使用的是同一个同步锁。

  • class A{ 
        public void test(A a) {
            synchronized(a){
                // 这样子可以实现不同对象有不同的锁
            }
        }
    }
    

如果针对对象要加同步锁,那就加在方法上。
如果针对某一段代码需要加同步锁,那就直接在代码块上加同步锁。

线程通信

// a 为临界资源
a.wait(); // 阻塞
a.notify();  // 唤醒
a.notifyAll(); 
// 这三个方法只能用在有同步锁的方法里面

生产者和消费者

public class Test3{
    public static void main(String[] args){
        Clerk c = new Clerk();
        // 生产者
        new Thread(new Runnable(){
            @Override
            public void run(){
                synchronized (c) {
                    while(true){
                        if(c.productNum == 0){
                            // 生产产品
                            c.productNum++;
                            c.notify; // 唤醒消费者
                        }else{
                            c.wait(); // 让生产者等待
                        }
                    }
                }
            }
        },"生产者").start();
        
        // 消费者
        new Thread(new Runnable(){
            @Override
            public void run(){
                synchronized (c) {
                    while(true){
                        if(c.productNum > 0){
                            // 消费产品
                            c.productNum--;
                            c.notify; // 唤醒生产者
                        }else{
                            c.wait(); // 让消费者者等待
                        }
                    }
                }
            }
        },"消费者").start();
    }
}

public class Clerk{
    public static int productNum = 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值