超牛牪犇Java之线程的等待与唤醒&反射

xiaoxiao2021-02-28  44

一.线程的等待与唤醒

例题:

利用三个线程间隔打印现成的名字 一共打印15次

1.用wait和notify或者notifyAll

写一个锁类 顺便写出计数的变量 和 标识

class MyLock{ private MyLock() { } public static final MyLock MY_LOCK = new MyLock(); public static int flag = 1; public static int num = 0; }

用来创建第一个线程的实现类

并且 为了让线程每次唤醒都重新判断标记 这里用while而不是if

class Print1Runnable implements Runnable{ @Override public void run() { while (true) { synchronized (MyLock.MY_LOCK) { if (MyLock.num == 150) { break; } MyLock.num++; while(MyLock.flag != 1) { try { MyLock.MY_LOCK.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); MyLock.flag = 2; //一个线程打印完 唤醒另外两个线程 MyLock.MY_LOCK.notifyAll(); } } } }

用来创建第二个线程的实现类

class Print2Runnable implements Runnable{ @Override public void run() { while (true) { synchronized (MyLock.MY_LOCK) { if (MyLock.num == 150) { break; } MyLock.num++; while (MyLock.flag != 2) { try { MyLock.MY_LOCK.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); MyLock.flag = 3; MyLock.MY_LOCK.notifyAll(); } } } }

用来创建第三个线程的实现类

class Print3Runnable implements Runnable{ @Override public void run() { while (true) { synchronized (MyLock.MY_LOCK) { if (MyLock.num == 150) { break; } MyLock.num++; while (MyLock.flag != 3) { try { MyLock.MY_LOCK.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); MyLock.flag = 1; MyLock.MY_LOCK.notifyAll(); } } } }

创建线程:

public static void main(String[] args) { Print1Runnable p1 = new Print1Runnable(); Thread t1 = new Thread(p1); Print2Runnable p2 = new Print2Runnable(); Thread t2 = new Thread(p2); Print3Runnable p3 = new Print3Runnable(); Thread t3 = new Thread(p3); t1.start(); t2.start(); t3.start(); }

2.用Lock锁完成

Condition对象 可以精准的控制哪一个线程等待或唤醒

newCondition方法

await方法

signal方法

创建锁类 并创建Condition对象 

class LockX{ private LockX() { // TODO Auto-generated constructor stub } public static final ReentrantLock LOCK_X = new ReentrantLock(); //创建Condition对象 public static final Condition c1 = LOCK_X.newCondition(); public static final Condition c2 = LOCK_X.newCondition(); public static final Condition c3 = LOCK_X.newCondition(); //创建计数器 public static int num = 0; public static int flag = 1; }

用来创建第一个线程的实现类

class P1Runnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub while (true) { LockX.LOCK_X.lock(); try { if (LockX.num == 150) { break; } LockX.num++; if (LockX.flag != 1) { //让当前线程等待 try { LockX.c1.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); LockX.flag = 2; LockX.c2.signal(); } finally { // TODO: handle finally clause LockX.LOCK_X.unlock(); } } } }

用来创建第二个线程的实现类

class P2Runnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub while (true) { LockX.LOCK_X.lock(); try { if (LockX.num == 150) { break; } LockX.num++; if (LockX.flag != 2) { //让当前线程等待 try { LockX.c2.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); LockX.flag = 3; LockX.c3.signal(); } finally { // TODO: handle finally clause LockX.LOCK_X.unlock(); } } } }

用来创建第三个线程的实现类

class P3Runnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub while (true) { LockX.LOCK_X.lock(); try { if (LockX.num == 150) { break; } LockX.num++; if (LockX.flag != 3) { //让当前线程等待 try { LockX.c3.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()); LockX.flag = 1; LockX.c1.signal(); } finally { // TODO: handle finally clause LockX.LOCK_X.unlock(); } } } }

创建线程:

public static void main(String[] args) { P1Runnable r1 = new P1Runnable(); Thread t1 = new Thread(r1); P2Runnable r2 = new P2Runnable(); Thread t2 = new Thread(r2); P3Runnable r3 = new P3Runnable(); Thread t3 = new Thread(r3); t1.start(); t2.start(); t3.start(); }

二.反射

一.  先要知道类是如何被加载的,可以分为三个过程

1.加载(把.class文件 加载到内存中)

        把编译的.class文件 加载到方法区

        在堆区创建了一个表示该Class文件的对象

2.连接

        验证  查看一下你这个类的内部结构(成员变量 成员方法)

        准备  为静态成员变量开辟内存空间 并且赋初始值

        解析  把方法中的局部变量进行替换  如:a = 1 ;

               是直接把这个局部变量的位置替换成1

3.初始化

咱们new一个对象 进行初始化(堆开空间 和之前一样)

二.  那么类什么时候会被加载?

简单来说: 类被使用的时候就会被加载

当使用子类的对象时父类会先被加载

三.  类是是用什么被加载的?

类是用类加载器被加载的

1. 根加载器 加载java的核心类库

2. 扩展加载器 加载ext路径下的一些类

3. 系统加载器 加载咱们放进去的第三方类库

反射

反射可以把一个正在运行的类(已经加载到内存中的类)

通过Class文件的对象 直接获取该文件中的成员变量和方法(私有权限的也能访问)

那么, 如何通过反射获取Class文件对象呢?

1.对象获取

2.类名获取

3.常用静态方法获取

Person p = new Person(); //对象获取 Class<? extends Person> c1 = p.getClass(); System.out.println(c1); //类名获取 Class<?> c2 = Person.class; System.out.println(c2); System.out.println(c1 == c2); //静态方法获取 //注意 使用类的全限定类名(包名+类名) Class<?> c3 = Class.forName("com.Commander.reflect.Person"); System.out.println(c3); //利用文件对象 直接获取类中的构造方法 Class<?> c = Class.forName("com.Commander.reflect.Person"); //获取构造方法的数组(只能获取public公有的构造方法 私有化的获取不到) Constructor<?>[] constructors = c.getConstructors(); //遍历 for (Constructor<?> constructor : constructors) { System.out.println(constructor); } //获取单个的构造方法 //参数是传入 可变参(...) 不传也行 //不传相当于获取的是无参的构造方法 Constructor<?> constructor = c.getConstructor(); System.out.println(constructor); //参数是文件的对象 Constructor<?> constructor2 = c.getConstructor(String.class,int.class); System.out.println(constructor2); //用这个构造方法 来创建对象 //可以通过向下转型调用类中的特有方法 Object object = constructor.newInstance(); System.out.println(object); //有参构造方法创建对象 Object object2 = constructor2.newInstance("taylor",30); System.out.println(object2);

直接利用文件对象 快速创建对象

前提:

1.构造方法必须是public修饰

2.类必须是public修饰

3.必须提供无参的构造方法

Class<?> c = Class.forName("com.Commander.reflect.Person"); Object object = c.newInstance(); System.out.println(object);

获取私有的构造方法 需要打开访问权限

Class<?> c = Class.forName("com.Commander.reflect.Person"); //获取私有的构造方法 //IllegalAccessException 没有访问该方法的权限 Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class,int.class); //打开访问权限 declaredConstructor.setAccessible(true); Object newInstance = declaredConstructor.newInstance("swift",10); System.out.println(newInstance);

获取成员变量并赋值

Class<?> c = Class.forName("com.Commander.reflect.Person"); //获取所有公开的成员变量 Field[] fields = c.getFields(); for (Field field : fields) { System.out.println(field); } //获取单个成员变量(传入成员变量的名字) Field field = c.getField("name"); //创建一个对象 Object object = c.newInstance(); //可以为对象中的这个成员变量赋值 field.set(object, "PC"); System.out.println(object); Field field2 = c.getDeclaredField("age"); //打开权限 field2.setAccessible(true); field2.set(object, 10); System.out.println(object); Class<?> c = Class.forName("com.Commander.reflect.Person"); //获取成员方法 Object object = c.newInstance(); Method method2 = c.getMethod("eat"); System.out.println(method2); //调用成员方法 //参数一表示用哪个对象调用该方法 //参数二表示方法传入的参数 //该方法的返回值 就是你所调用的成员方法产生的返回值 Object invoke = method2.invoke(object); System.out.println("我是方法的返回值" + invoke); Method method3 = c.getMethod("speak",String.class); Object invoke1 = method3.invoke(object,"hahaha"); Method declaredMethod = c.getDeclaredMethod("playGame",String.class); declaredMethod.setAccessible(true); declaredMethod.invoke(object, "WarFrame"); //获得所有公开的方法()包括继承的 Method[] methods = c.getMethods(); for (Method method : methods) { System.out.println(method); }

利用反射向ArrayList<String>中添加Integeer数据

tips:编译成.Class文件后 代码中不存在泛型

ArrayList<String> list = new ArrayList<>(); Class<?> class1 = list.getClass(); Method method = class1.getMethod("add", Object.class); System.out.println(method); Object invoke = method.invoke(list, 123); method.invoke(list, 456); method.invoke(list, 789); method.invoke(list, new Person()); for (Object object : list) { System.out.println(object); }
转载请注明原文地址: https://www.6miu.com/read-2623748.html

最新回复(0)