一.线程的等待与唤醒
例题:
利用三个线程间隔打印现成的名字 一共打印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);
}