1、多线程
1.1 程序、进程、线程
- 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
- 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
1.2 多线程的优缺点
优点:资源利用率更好;程序设计在某些情况下更简单;程序响应更快
缺点:设计更复杂、上下文切换的开销
1.3 创建线程
第一种方法
-
创建子类继承Thread类,重写子类中的run方法
-
创建Thread类的子类的对象
-
调用子类对象的Start方法,开启新线程,执行其中的run方法
public class Demo01 {
public static void main(String[] args) throws InterruptedException {
//2、创建Thread类的子类的对象
Mythread t = new Mythread();
//3、调用子类对象的Start方法,开启新线程,执行其中的run方法
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1);//本线程休眠,单位毫秒
System.out.println("main->"+i);
}
}
}
//1、创建子类继承Thread类,重写子类中的run方法
class Mythread extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1);//本线程休眠,单位毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Tread->"+i);
}
}
}
第二种方法
-
创建一个类实现Runnable接口,重写其中的run方法
-
创建Thread类的对象,将Runnable的实现类对象作为参数传入
-
调用Thread类中的start方法,开启新线程,执行其中的run方法
public class Demo02Runnable {
public static void main(String[] args) throws InterruptedException {
//3、创建Thread类的对象,将Runnable的实现类对象作为参数传入
Thread t = new Thread(new Mythread1());
//4、调用Thread类中的start方法,
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(100);
System.out.println("我在听廖老师讲课");
}
}
}
//1、创建一个类实现Runnable接口
class Mythread1 implements Runnable{
//2、重写其中的run方法
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我在和辅导员聊天");
}
}
}
1.4 线程的五种状态
1)、新生状态: new
2)、就绪状态: runnable
3)、运行状态: running
4)、阻塞状态: blocked
5)、执行完毕: dead
1.5 线程同步
当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。
要解决上述多线程并发访问一个资源的安全性问题:也就是解决重复票与不存在票问题,Java中提供了同步机制 (synchronized)
来解决。
同步锁:
synchronized(同步锁){ 需要同步操作的代码 }
同步方法:
public synchronized void method(){
可能会产生线程安全问题的代码
}
1.6 线程死锁
1.7 线程死锁的解决方案
-
往往是程序逻辑的问题。需要修改程序逻辑。
-
尽量不要同时持有两个对象锁
2、反射
2.1 反射的功能
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理
2.2 获取源头Class
-
通过对象获取
-
通过类获取
-
通过字符串获取
public static void main(String[] args) throws Exception { //第一种:class.forName("全类名") Class clz1 = Class.forName("com.sxt.hw.Person"); System.out.println(clz1);//class com.sxt.hw.Person //第二种:类名.class Class clz2 = Person.class; System.out.println(clz2);//class com.sxt.hw.Person //第三种:对象.getClass Person p = new Person(); Class clz3 = p.getClass(); System.out.println(clz3);//class com.sxt.hw.Person //验证三个对象是否是同一个 System.out.println(clz1 == clz2);//true System.out.println(clz1 == clz3);//true //同一个字节码文件在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个 }
2.3 获取成员变量
-
getFields()
-
getField()
-
getDeclaredFields()
-
getDeclaredField()
public static void main(String[] args) throws Exception { //0、获取Class对象 Class<Person> clz = Person.class; //1、获取所有的public修饰的成员变量 Field[] fields = clz.getFields(); for (Field temp : fields) { System.out.println(temp);//public java.lang.String com.sxt.hw.Person.a } System.out.println("-------------------"); //2、获取成员变量a的值 Field a = clz.getField("a"); Person p = new Person(); Object v = a.get(p); System.out.println(v);//null //3、设置成员变量a 的值 a.set(p,"张三"); System.out.println(p);//Person{name='null', age=0, a='张三', b='null', c='null', d='null'} System.out.println("-------------------"); //1、获取所有成员变量,不考虑修饰符 Field[] dfs = clz.getDeclaredFields(); for (Field temp : dfs) { System.out.println(temp);// } System.out.println("-------------------"); //2、获取私有成员变量b 的值 Field b = clz.getDeclaredField("b"); System.out.println(b); v = b.get(p); System.out.println(v);//null //3、设置私有成员变量b 的值 b.set(p,"李四"); System.out.println(p);//Person{name='null', age=0, a='张三', b='李四', c='null', d='null'} }
2.4 创建构造器
- getConstructors()获取所有的public权限的构造器
- getDeclaredConstructors()获取所有的构造器
- getConstructor()
- getConstructors()
- newInstance() 创建对象
public static void main(String[] args) throws Exception {
//0、获取Person的Class对象
Class clz = Person.class;
//获取构造方法
Constructor c = clz.getConstructor(String.class, int.class);
System.out.println(c);//public com.sxt.hw.Person(java.lang.String,int)
//创建对象
Object p = c.newInstance("张三", 23);
System.out.println(p);//Person{name='张三', age=23, a='null', b='null', c='null', d='null'}
//获取所有构造参数
Constructor[] dcs = clz.getDeclaredConstructors();
for (Constructor temp : dcs) {
System.out.println(temp);//public com.sxt.hw.Person()
//public com.sxt.hw.Person(java.lang.String,int)
}
}
2.5 创建成员方法
- getMethods()
- getMethod()
- getDeclaredMethods()
- getDeclaredMethods()
- invoke()
public static void main(String[] args) throws Exception {
Class<Person> clz = Person.class;
//获取类名
String className = clz.getName();
System.out.println(className);//com.sxt.hw.Person
//获取指定的方法名
Method eatMethod = clz.getMethod("eat",String.class);
//创建对象
Person p = new Person();
//执行方法
eatMethod.invoke(p,"张三");//张三eat......
System.out.println("-------------");
//获取所有public修饰的方法
Method[] methods = clz.getMethods();
for (Method temp :methods) {
//获取方法名
temp.getName();
System.out.println(temp);
}
}