一.多线程
三个线程间隔打印线程名
方法一:
public class Day25{
public static void main(String[] args) {
Thread thread1 = new Thread(new printARunnable());
Thread thread2 = new Thread(new printBRunnable());
Thread thread3 = new Thread(new printCRunnable());
//开启线程
thread1.start();
thread2.start();
thread3.start();
}
}
//定义锁类
class ILock{
private ILock(){
}
public static final ILock LOCK = new ILock();
//定义标识符
public static int flag = 1;
//定义循环标识符
public static int num = 0;
}
//线程实现类
class printARunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (ILock.LOCK) {
//结束循环条件
if (ILock.num == 150){
break;
}
//自增
ILock.num++;
//使用while循环是唤醒的被线程重新进入判断,是否进入等待
while (ILock.flag != 1) {
try {
ILock.LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//切换标记
ILock.flag = 2;
//唤醒等待的所有线程
ILock.LOCK.notifyAll();
}
}
}
}
class printBRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (ILock.LOCK) {
//结束循环
if (ILock.num == 150){
break;
}
ILock.num++;
//判断
while (ILock.flag != 2) {
try {
ILock.LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//切换标记
ILock.flag = 3;
ILock.LOCK.notifyAll();
}
}
}
}
class printCRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (ILock.LOCK) {
//结束循环
if (ILock.num == 150){
break;
}
ILock.num++;
//判断
while (ILock.flag != 3) {
try {
ILock.LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//切换标记
ILock.flag = 1;
ILock.LOCK.notifyAll();
}
}
}
}
方法2:
使用Lock锁
public class Day25 {
public static void main(String[] args) {
Thread thread1 = new Thread(new PrintARunnable());
Thread thread2 = new Thread(new PrintBRunnable());
Thread thread3 = new Thread(new PrintCRunnable());
//开启线程
thread1.start();
thread2.start();
thread3.start();
}
}
//声明锁
class LockA{
private LockA() {
}
//声明lock锁
public static final ReentrantLock LOCK = new ReentrantLock();
//声明三个Condition对象(从使用的lock锁中获取)
public static final Condition c1 = LOCK.newCondition();
public static final Condition c2 = LOCK.newCondition();
public static final Condition c3 = LOCK.newCondition();
//声明标记
public static int flag = 1;
//声明计数
public static int num = 0;
}
实现接口类
class PrintARunnable implements Runnable{
public void run() {
while (true) {
//加锁
LockA.LOCK.lock();
try {
if (LockA.num == 150) {
break;
}
LockA.num++;
//判断标记
if (LockA.flag != 1) {
//利用Condition对象将线程1等待
try {
//指定线程等待
LockA.c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//修改标记
LockA.flag = 2;
//唤醒指定的线程
LockA.c2.signal();
} finally {
//关锁
LockA.LOCK.unlock();
}
}
}
}
class PrintBRunnable implements Runnable{
public void run() {
while (true) {
//加锁
LockA.LOCK.lock();
try {
if (LockA.num == 150) {
break;
}
LockA.num++;
//判断标记
if (LockA.flag != 2) {
//利用Condition对象将线程1等待
try {
LockA.c2.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//修改标记
LockA.flag = 3;
//唤醒指定的线程
LockA.c3.signal();
} finally {
// TODO: handle finally clause
//关锁
LockA.LOCK.unlock();
}
}
}
}
class PrintCRunnable implements Runnable{
public void run() {
while (true) {
//加锁
LockA.LOCK.lock();
try {
if (LockA.num == 150) {
break;
}
LockA.num++;
//判断标记
if (LockA.flag != 3) {
//利用Condition对象将线程1等待
try {
LockA.c3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
//修改标记
LockA.flag = 1;
//唤醒指定的线程
LockA.c1.signal();
} finally {
//关锁
LockA.LOCK.unlock();
}
}
}
}
二.反射
1.类的加载
1).加载
将类的.class文件加载到方法区,创建一个class对象相当于文件的对象
2).连接
验证 验证类的内部结构成员变量和方法
准备 为静态变量开辟空间赋初始值
解析 将局部变量进行替换
3).初始化
创建对象 new对象
类的加载时机是当类被调用的时候
2.类的加载器
加载类使用类加载器
1.根加载器 加载JDK的lib文件夹下的jar文件
2.扩展加载器 加载ext文件夹下的文件
3.系统加载器 自定义类或导入的jar包
3.反射
反射可以将一个正在与进行的类,通过这个Class文件对象直接获取类内部的方法和成员变量
/*
* 获取class文件对象
* 1.通过对象获取
* 2.通过类获取
* 3.通过class中的静态方法获取(Class.ForName()常用)
*/
public class Demo25 {
public static void main(String[] args) {
vate static void fn2() throws Exception {
//使用class文件对象 快速创建对象
//前提:1.类使用public修饰 2.必须提供无参数的构造方法 3.该无参的构造方法必须是public修饰
Class<?> class1 = Class.forName("day25.Person");
Object object = class1.newInstance();
System.out.println(object);
//获取类中所有的构造方法包括私有
Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println(constructor);
}
//获取私有的构造方法
Constructor<?> declaredConstructor = class1.getDeclaredConstructor(int.class, String.class);
//开启权限
declaredConstructor.setAccessible(true);
//创建对象
Object object2 = declaredConstructor.newInstance(18, "李四");
System.out.println(object2);
//获取所有成员变量(公开的)
Class<?> class1 = Class.forName("day25.Person");
Field[] fields = class1.getFields();
for (Field field : fields) {
System.out.println(field);
}
Field field = class1.getField("name");
//通过反射给该属性赋值
Object object = class1.newInstance();
field.set(object, "张三");
System.out.println(object);
//获取私有成员变量赋值
Field declaredField = class1.getDeclaredField("age");
declaredField.setAccessible(true);
declaredField.set(object, 20);
System.out.println(object);
}
}
private static void fn() throws Exception {
// 1.通过对象获取
Person person = new Person();
Class<? extends Person> class1 = person.getClass();
System.out.println(class1);
//通过类获取
Class<? extends Person> class2 = person.getClass();
System.out.println(class2);
//常用 只需要一个字符串就能获取该类的class对象 <?>表示通配
Class<?> class3 = Class.forName("day25.Person");
System.out.println(class3);
//通过Class文件对象获取构造方法
//获取所有public共有的构造方法
Constructor<?>[] constructors = class3.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//获取单个的构造方法
//无参数构造方法
Constructor<?> constructor = class3.getConstructor();
System.out.println(constructor);
//有参数构造方法
//参数是参数类的文件类型
Constructor<?> constructor2 = class3.getConstructor(String.class, int.class);
System.out.println(constructor2);
//创建对象并赋值
Object object = constructor2.newInstance("李四", 18);
System.out.println(object);
}
练习:
利用反射完成以下方法
1.此方法可将obj对象中名为propertyName的属性的值设置为value.
参数:
赋值对象
属性名字
给该属性赋值
2.此方法可以获取obj对象中名为propertyName的属性的值
public class Day25{
public static void main(String[] args) throws Exception {
Class<?> class1 = Class.forName("com.lanou3g.reflet.Person");
//获取类中所有的公开方法(包括父类的)
Method[] methods = class1.getMethods();
//获取指定的成员方法
//参数name 方法名 参数2 获取参数的?Class类型
//public void eat()
Method method2 = class1.getMethod("eat");
System.out.println(method2);
Object object = class1.newInstance();
//调用该方法
//参数1:调用该方法的对象 参数2:调用该方法要传入的参数 返回值:调用该方法 方法的返回值
Object rel = method2.invoke(object);
System.out.println(rel);
Method method = class1.getMethod("speak", String.class);
Object rel2 = method.invoke(object, "哈哈哈");
System.out.println(rel2);
Method method3 = class1.getDeclaredMethod("play", String.class);
//开启权限
method3.setAccessible(true);
//调用
Object rel3 = method3.invoke(object, "KPL");
System.out.println(rel3);
Class<?> class1 = Class.forName("com.lanou3g.reflet.Person");
Object object = class1.newInstance();
setObjectValue(object, "name", "lisi");
System.out.println(object);
Object objectValue = getObjectValue(object, "age");
System.out.println(objectValue);
}
}
利用反射
向ArraryList中 添加 Integer数据 Person对象
注意:编译成Class文件 泛型不存在
public class Demo03 {
public static void main(String[] args) throws Exception {
ArrayList<String> list = new ArrayList<>();
//获取class文件对象
Class<? extends ArrayList> class1 = list.getClass();
//获取方法
Method method = class1.getMethod("add", Object.class);
//调用方法
method.invoke(list, 123);
method.invoke(list, new Person("张三", 19));
System.out.println(list);
}
public static void fn1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException {
Class<?> class1 = Class.forName("com.lanou3g.reflet.Person");
//获取类中所有的公开方法(包括父类的)
Method[] methods = class1.getMethods();
//获取指定的成员方法
//参数name 方法名 参数2 获取参数的?Class类型
Method method2 = class1.getMethod("eat");
System.out.println(method2);
Object object = class1.newInstance();
//调用该方法
//参数1:调用该方法的对象 参数2:调用该方法要传入的参数 返回值:调用该方法 方法的返回值
Object rel = method2.invoke(object);
System.out.println(rel);
//public void speak(String str)
Method method = class1.getMethod("speak", String.class);
//System.out.println(method);
Object rel2 = method.invoke(object, "哈哈哈");
System.out.println(rel2);
Method method3 = class1.getDeclaredMethod("play", String.class);
//开启权限
method3.setAccessible(true);
//调用
Object rel3 = method3.invoke(object, "KPL");
System.out.println(rel3);
}
}