一.ReetrantLock锁中的 Condition对象
Condition对象中提供方法
- await();等待
- signal();唤醒(指定某一个线程被唤醒)
需求:使用lock锁 间隔打印三个线程
代码:
public class Kll {
public static void main(String[] args) {
Thread t1 = new Thread(new PrintA());
Thread t2 = new Thread(new PrintB());
Thread t3 = new Thread(new PrintC());
t1.start();
t2.start();
t3.start();
}
}
// 声明锁
class MyLockA {
private MyLockA() {
}
// 声明lock锁
public static final ReentrantLock LOCK_A = new ReentrantLock();
// 声明三个Condition对象(从使用的lock锁中获取)
public static final Condition c1 = LOCK_A.newCondition();
public static final Condition c2 = LOCK_A.newCondition();
public static final Condition c3 = LOCK_A.newCondition();
// 声明标记
public static int flag = 1;
// 计数
public static int num = 0;
}
class PrintA implements Runnable {
@Override
public void run() {
while (true) {
// 加锁
MyLockA.LOCK_A.lock();
try {
// 循环结束条件
if (MyLockA.num == 150) {
break;
}
MyLockA.num++;
// 判断标记
if (MyLockA.flag != 1) {
// 利用Condition对象将1号线程等待了
try {
MyLockA.c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + MyLockA.num);
// 修改标记
MyLockA.flag = 2;
// 唤醒指定的线程
MyLockA.c2.signal();
} finally {
// 关锁
MyLockA.LOCK_A.unlock();
}
}
}
}
class PrintB implements Runnable {
@Override
public void run() {
while (true) {
// 加锁
MyLockA.LOCK_A.lock();
try {
// 循环结束条件
if (MyLockA.num == 150) {
break;
}
MyLockA.num++;
// 判断标记
if (MyLockA.flag != 2) {
// 利用Condition对象将1号线程等待了
try {
MyLockA.c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + MyLockA.num);
// 修改标记
MyLockA.flag = 3;
// 唤醒指定的线程
MyLockA.c3.signal();
} finally {
// 关锁
MyLockA.LOCK_A.unlock();
}
}
}
}
class PrintC implements Runnable {
@Override
public void run() {
while (true) {
// 加锁
MyLockA.LOCK_A.lock();
try {
// 循环结束条件
if (MyLockA.num == 150) {
break;
}
MyLockA.num++;
// 判断标记
if (MyLockA.flag != 3) {
// 利用Condition对象将1号线程等待了
try {
MyLockA.c3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + MyLockA.num);
// 修改标记
MyLockA.flag = 1;
// 唤醒指定的线程
MyLockA.c1.signal();
} finally {
// 关锁
MyLockA.LOCK_A.unlock();
}
}
}
}
二.类的加载
1.类是如何加载的?
- 1.加载
- 将类的.class文件加载到方法区
- 创建一个Class对象(表示的就是.class文件) 相当于文件的对象
- 2.连接
- 验证 验证一下类的内部结构(成员变量 和 方法)
- 准备 为静态变量开辟空间,赋初始值
- 解析 将局部变量进行替换 替换成对应的值
- int a = 10 下面将所有的a 直接替换成 10
- 3.初始化
- 创建对象 new对象(堆内存开辟空间,与之前一样)
- 2.类是什么时候加载的?(加载时机)
- 使用时,该类一定会被加载
- 加载该类时,会先加载该类的父类
- 不重复加载
- 3.类是用什么加载的?(使用类加载器加载的)
- 1.根加载器 加载JDK的lib文件夹下的jar文件
- 2.扩展加载器 加载ext文件夹下的文件
- 3.系统加载器 咱们自定义类或者导入jar都是用系统加载器
三.反射
反射可以将正在运行的类(加载完成的类),
通过这个class文件的对象 ,可以直接获取类内部的所有成员方法和成员变量(包括私有的).
1.获取Class文件对象的3种方法
1.通过对象获取
2.通过类获取
3.通过class中的静态方法获取(class.forName() 常用)
person类
public class Person {
public String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
// 私有构造方法
private Person(int age, String name) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "[name=" + name + ", age=" + age + "]";
}
// 吃饭方法
public void eat() {
System.out.println("吃饭");
}
// 说话
public void speak(String string) {
System.out.println("说的是:" + string);
}
// 打游戏
private int play(String game) {
System.out.println("玩的是:" + game);
return 123;
}
}
获取Class对象文件的方式代码:
public class Kll {
public static void main(String[] args) throws Exception {
// 1.通过对象获取
Person p = new Person();
// 获取Person类的Class文件对象
Class<? extends Person> c1 = p.getClass();
System.out.println(c1);
// 2.通过类获取
Class<Person> c2 = Person.class;
System.out.println(c2);
// 3.常用的 (只需用一个字符串 就能获取该类的class对象)
// 注意参数要填全类名 包名+类名
Class<?> c3 = Class.forName("com.lanou3g.reflect.Person");
System.out.println(c3);
}
}
通过class文件对象,快速创建对象
- 前提:
- 1.类必须是用Public修饰
- 2.必须提供无参构造方法
- 3.该无参的构造方法必须是public修饰
public class Kll {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 快速创建对象(直接使用类中无参构造方法创建的)
Object object = c.newInstance();
System.out.println(object);
}
}
获取构造方法, 利用获取的创建对象.
代码如下:
public class Kll {
public static void main(String[] args) throws Exception {
// 通过Class文件对象获取 类中构造方法
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 获取所有public修饰的构造方法
Constructor<?>[] constructors = c.getConstructors();
// 遍历
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取指定的构造方法
Constructor<?> constructor = c.getConstructor();
System.out.println(constructor);
// 利用该构造方法创建对象
Object object = constructor.newInstance();
System.out.println(object);
// 有参的构造方法创建对象(参数是 参数类的文件类型)
Constructor<?> constructor2 = c.getConstructor(String.class, int.class);
// 创建对象
Object object2 = constructor2.newInstance("kll", 20);
System.out.println(object2);
// 获取类中所有的构造方法(包括私有)
Constructor<?>[] constructors1 = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors1) {
System.out.println(constructor);
}
// 获取私有构造方法
Constructor<?> constructorp = c.getDeclaredConstructor(int.class, String.class);
// 打开私有方法使用权限
constructorp.setAccessible(true);
// 创建对象
Object object1 = constructorp.newInstance(20, "kll");
// 打印对象
System.out.println(object1);
}
}
获取所有成员变量,代码如下:
public class Kll {
public static void main(String[] args) throws Exception {
// 获取所有公开的成员变量
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 单独获取指定的成员变量
Field field = c.getField("name");
System.out.println(field);
// 创建person对象
Object object = c.newInstance();
// 通过反射给该属性赋值
field.set(object, "会给");
System.out.println(object);
// 获取私有成员变量 age 并且赋值打印
Field field2 = c.getDeclaredField("age");
// IllegalAccessException异常 需要打开权限 打开访问使用权限
field2.setAccessible(true);
// 赋值
field2.set(object, 20);
System.out.println(object);
}
}
获取所有成员方法代码:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.omg.CORBA.PUBLIC_MEMBER;
public class Kll {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 获取类中所有的公开的方法(包括父类的)
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取指定公开的成员方法
// 参数1:方法名
// 参数2:获取的方法的参数的Class类型
Method method = c.getMethod("eat");
System.out.println(method);
// 创建对象
Object obj = c.newInstance();
// 调用该方法
// 参数1:调用该方法的对象
// 参数2:调用该方法,要传入的参数
// 返回值:调用该方法 方法的返回值
Object invoke = method.invoke(obj);
System.out.println(invoke);
Method method2 = c.getMethod("speak", String.class);
Object invoke2 = method2.invoke(obj, "国语教学");
System.out.println(invoke2);
// 获取指定方法
Method method3 = c.getDeclaredMethod("play", String.class);
// 开权限
method3.setAccessible(true);
// 调用方法,接收返回值
Object invoke3 = method3.invoke(obj, "王者");
// 打印返回值
System.out.println(invoke3);
}
}