多线程和反射
1. 多线程编程
1.1 什么是进程
就是在计算机中运行的独立程序,例如:QQ 微信 网易云。这些程序是直接申请系统资源,系统资源包括: CPU使用率 内存占用率 硬盘,网络和显卡。
进程:
1. 互斥!!!
2. 独立!!!
1.2 什么是线程
线程就是进程中一部分,也可以认为是进程的一个功能模块。例如 电脑管家 可以同时执行 杀毒 清理 一键加速 体检。
线程使用的资源是当前进程中分配的资源。每一个线程之间存在【共享资源】。同时在软件开发中,所有的线程都是【抢占式运行】。CPU执行线程会存在一个【单位时间片】概念。
windows操作系统被称之多任务操作系统。只不过是在单位时间内,不同的软件直接进行跳转执行,单位时间足够短!!!
1.3 线程和进程的关系
一个进程最少有一个线程!!!如果进程中没有任何一个线程存在,当前进程退出!!!线程分两大类 前台线程和守护线程。
【面试题】
Java程序中最少有几个线程???
任何一个Java程序最少两个线程
一个main主线程,不是main方法!!!
一个GC线程,Garbage Collection JVM的垃圾回收机制。
1.4 多线程的优缺点
中国的古话:
物极必反!!!
优点:
1. 可以提高资源利用率
2. 可以增加用户体验
缺点:
1. 增加了系统资源压力
2. 降低了用户体验,多线程情况下,会导致卡顿问题。
3. 容易导致死锁!!!
4. 会导致共享资源冲突问题。
1.5 Java中自定义线程类的两种方式
1. 继承Thread类
Thread类是Java中所有线程的基类,Thread类配套线程操作方法
2. 遵从Runnable接口
实现Runnable接口中方法run方法
package com. qfedu. a_thread ;
class MyThread1 extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( "继承Thread类,自定义线程对象" ) ;
}
}
}
class MyThread2 implements Runnable {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( "遵从Runnable接口,实现自定义线程" ) ;
}
}
}
public class Demo1 {
public static void main ( String [ ] args) {
MyThread1 mt1 = new MyThread1 ( ) ;
mt1. start ( ) ;
Thread mt2 = new Thread ( new MyThread2 ( ) ) ;
mt2. start ( ) ;
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( "main方法线程......." ) ;
}
}
}
1.6 多线程涉及到的方法
构造方法:
Thread();
创建一个啥也没有线程对象,没有执行目标和线程自有名称。
Thread(Runnable target);
提供给当前线程对象一个执行目标,参数是Runnable接口实现类对象,线程名称是
系统默认的线程名称
Thread(Runnable target, String threadName);
提供给当前线程对象一个执行目标,同时赋予对应的线程名。
成员方法:
void setName(String name);
设置当前线程的名字
String getName();
获取当前线程的名字
void setPriority(int newPriority);
设置当前线程的优先级~~~优先级有范围约束 1 ~ 10 10最大 1最小 5默认
优先级只能决定当前线程的执行概率,不保证执行顺序。
int getPriority();
获取当前线程的优先级
static Thread currentThread();
在哪一个线程代码中执行,获取当前线程对象。
static void sleep(int ms) throws InterruptedException
在哪一个线程中执行,当前线程休眠对应的毫秒数
1.7 线程同步问题【重点】
1.7.1 多线程实际问题分析
<<金刚川>> 二七万达 IMAX 100张
销售渠道:
淘票票 猫眼 美团
三个销售线程 ==> 100张票是一个共享资源!!!
销售线程代码
共享资源处理
1.7.2 多线程共享资源问题分析
100张票需要保存的变量特征:
1. 共享性
2. 持久性
变量:
成员变量
持久性,独立性
局部变量
啥也不是~~~
静态成员变量
共享性,持久性
权限修饰符:
私有 private修饰,不能对外公开使用,可以提供给用户一个查看消息的方法。
公开
class SaleThread implements Runnable {
@Override
public void run() {
// 线程销售代码
}
}
main() {
new Thread(new SaleThread(), "淘票票").start();
new Thread(new SaleThread(), "猫眼").start();
new Thread(new SaleThread(), "美团").start();
}
1.7.3 多线程共享代码部分使用和问题
1.7.4 同步代码块加锁
同步代码块中,有且只允许一个线程对象执行,进入同步代码块,自动落锁,线程执行完毕,超出同步代码块范围以内,自动开锁。
格式:
synchronized (锁·对象) {
}
1. 锁对象可以是任意对象!!!
2. 同步代码块中有且只能运行一个线程执行。
3. 在需要进行同步限制的线程中,锁对象必须是惟一的。
package com. qfedu. a_thread ;
class SaleThread implements Runnable {
private static int tickets = 1000 ;
@Override
public void run ( ) {
while ( true ) {
synchronized ( "锁" ) {
if ( tickets > 0 ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "售出了" + tickets + "张票" ) ;
tickets-- ;
} else {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ": 没票了,铁汁" ) ;
break ;
}
}
}
}
}
public class Demo3 {
public static void main ( String [ ] args) {
Thread t1 = new Thread ( new SaleThread ( ) , "淘票票" ) ;
Thread t2 = new Thread ( new SaleThread ( ) , "猫眼" ) ;
Thread t3 = new Thread ( new SaleThread ( ) , "美团" ) ;
t1. start ( ) ;
t2. start ( ) ;
t3. start ( ) ;
}
}
2. 反射 【重点】
2.1 Java中定义类的格式
class 类名 {
成员变量 Field
构造方法 Constructor
成员方法 Method
}
类名 ==> 对于整个大括号以内的内容封装
整个class是包含当前数据类型的所有内容,当前数据类型的名字是类名 Class
2.2 Java文件和class的关系
Java文件就是.java结尾的一个文件,保存对应class的所有内容
2.3. .class字节码文件和Java文件的关系
.class字节码文件 ==> Java文件通过 javac Java编译器编译之后得到的可以提供给JVM执行的二进制文件。
.class文件中是否包含整个Java内容??? 是的
.class文件中包含整个class对应的所有内容??? 是的
2.4 类文件(.class)加载过程,内存分析
2.5 万恶之源 Class对象
Java中把.class字节码文件占用的【方法区】内存空间,看作是一个对象。Class类对象。
妙~十遍
Class Class.forName(String packageNameAndClassName);
根据指定的完整包名.类名获取对应的Class对象。存在异常抛出
ClassNotFoundException
Class 类对象.getClass();
通过类对象获取当前类对象对应的Class对象。
Class 类名.class;
通过类名获取class属性。
package com. qfedu. b_reflect ;
public class GetClassObject {
public static void main ( String [ ] args) throws ClassNotFoundException {
Class cls1 = Class . forName ( "com.qfedu.b_reflect.Person" ) ;
Class < ? extends Person > cls2 = new Person ( ) . getClass ( ) ;
Class cls3 = Person . class ;
System . out. println ( cls1) ;
System . out. println ( cls2) ;
System . out. println ( cls3) ;
System . out. println ( cls1 == cls2) ;
System . out. println ( cls2 == cls3) ;
System . out. println ( cls3 == cls1) ;
}
}
2.6 Constructor类对象获取
2.6.1 构造方法必要条件
构造方法
一样: 方法名 ==> 类名
不一样:
形式参数列表 参数列表,参数个数,参数顺序。
权限修饰符 公开的或者私有的
如果想要获取一个构造方法:
参数情况 【类型】
权限修饰符
2.6.2 获取Constructor对象方法
Constructor[] getConstructors();
通过Class对象调用,获取当前类内的所有非私有化构造方法对象数组
Constructor[] getDeclaredConstructors();
【暴力反射】
通过Class对象调用,获取当前类内的所有构造方法对象数组,包括私有化构造方法
Constructor getConstructor(Class... initParameterTypes);
通过Class类对象调用,获取当前类内指定数据类型的非私有化构造方法类对象
案例:
无参数构造方法 public Person();
cls.getConstructor();
有参数构造方法 public Person(int, String);
cls.getConstructor(int.class, String.class);
类型.class来告知编译器,这里需要的数据类型是哪一个。
Constructor getDeclaredConstructor(Class... initParameterTypes);
【暴力反射】
通过Class类对象调用,获取当前类内指定的数据类型构造方法,包含私有化构造方法
案例:
String类型私有化构造方法 private Person(String);
cls.getDeclaredConstructor(String.class);
Object newInstance(Object... initParameters);
Object... 这里需要的参数是Object类型,个数不限,但是需要对应当前构造方法对象的参数列表顺序,个数和类型。
Constructor con ==> public Person(int, String);
Person p = (Person) con.newInstance(10, "苟磊");
package com. qfedu. b_reflect ;
import java. lang. reflect. Constructor ;
import java. lang. reflect. InvocationTargetException ;
public class GetConstructorObject {
public static void main ( String [ ] args)
throws ClassNotFoundException , NoSuchMethodException , SecurityException ,
InstantiationException , IllegalAccessException , IllegalArgumentException ,
InvocationTargetException {
Class cls1 = Class . forName ( "com.qfedu.b_reflect.Person" ) ;
Constructor [ ] constructors = cls1. getConstructors ( ) ;
for ( Constructor constructor : constructors) {
System . out. println ( constructor) ;
}
System . out. println ( ) ;
Constructor [ ] declaredConstructors = cls1. getDeclaredConstructors ( ) ;
for ( Constructor constructor : declaredConstructors) {
System . out. println ( constructor) ;
}
System . out. println ( ) ;
Constructor con1 = cls1. getConstructor ( ) ;
Constructor con2 = cls1. getConstructor ( int . class ) ;
Constructor con3 = cls1. getConstructor ( int . class , String . class ) ;
System . out. println ( con1) ;
System . out. println ( con2) ;
System . out. println ( con3) ;
Constructor con4 = cls1. getDeclaredConstructor ( String . class ) ;
System . out. println ( con4) ;
System . out. println ( ) ;
Person p = ( Person ) Class
. forName ( "com.qfedu.b_reflect.Person" )
. getConstructor ( int . class , String . class )
. newInstance ( 1 , "苟磊" ) ;
System . out. println ( p) ;
Person person = new Person ( 1 , "苟磊" ) ;
System . out. println ( person) ;
Person object = getObject ( Person . class ) ;
System . out. println ( object) ;
con4. setAccessible ( true ) ;
Object newInstance = con4. newInstance ( "测试" ) ;
System . out. println ( newInstance) ;
}
public static < T > T getObject ( Class < T > cls)
throws InstantiationException , IllegalAccessException , IllegalArgumentException ,
InvocationTargetException , NoSuchMethodException , SecurityException {
return cls. getConstructor ( ) . newInstance ( ) ;
}
}
【补充知识点 给予暴力反射操作权限】
con4. setAccessible ( true ) ;