多线程和反射

一.多线程
三个线程间隔打印线程名
方法一:

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);
	}
}

猜你喜欢

转载自blog.csdn.net/l710820742/article/details/82844336