反射和多线程基础

一、今日内容

1.1 课程回顾
1.2 反射是啥
1.3 进程和线程
1.4 线程的创建方式
1.5 线程的状态
1.6 线程的常用方法

二、课程回顾

Java的基本语法:

​ 1.数据类型:基本、引用

​ 2.运算符:算术、逻辑、比较、赋值、位、三目

​ 3.表达式

​ 4.顺序结构

​ 5.分支结构:选择结构:if switch

6.循环结构:for while do/while

Java:面向对象:

1.最终的目的:消除重复代码

2.核心:类和对象

3.特征:封装、继承、多态、抽象

4.关键字:static,public,private、class、interface this super 等

5.抽象类和接口

Java中数组:

数组:存储多个相同数据类型的数据结构

特点:长度固定

声明和初始化:数据类型 [] 变量名=初始化;动态初始化、静态初始化

索引:索引从0开始

算法:

1.排序算法

2.查找算法

多维数组:Java允许数组的元素又是一个数组

Java中的集合:

集合:存储多个指定数据类型的元素。

特点:长度可变,存储引用类型

种类:List、Set、Map

常用的集合类:ArrayList、HashMap、TreeSet等

泛型:引用类型的占位符 出现好处:代替了Object,避免了转型(向上转型、向下转型)

Java中的流:

File:Java中操作文件或目录的类。记忆:常用的方法:创建、删除、重命名、获取

流:数据通信的通道。

根据功能分:节点流、过滤流

根据单位分:字节流、字符流

根据方向分:输入流、输出流

Java的节点流:文件流(操作的数据都是跟文件有关):Filexxx. 内存流(操作的数据都是跟数组有关):Bytexxx

Java的过滤流:缓冲流、对象流、数据流、转换流等等

输入流:read(读取)、skip(跳过)

输出流:write(写出)、flush(刷新)

Java中的异常:

异常:Java主要分为:Error:人为不可解决、Exception:异常,运行的特点:运行时异常、编译时异常

编译异常:代码在编译阶段,显示的异常 IOException

运行异常:代码在运行阶段,显示的异常 RuntimeException、IndexOutofException

自定义异常:自定义类并继承Exception

三、Java中的反射

3.1 反射是什么

反射机制是Java程序,在运行中,动态获取类的信息(方法、属性、注解等)、并且还可以调用类的属性、和方法。这种动态获取类的信息、以及动态调用对象的方法和属性的行为就叫反射。

反射:就是可以获取类的信息、和执行方法。

3.2 反射可以做什么

1.运行时获取类中的属性

2.运行时获取类中的方法

3.运行时创建类的对象

4.运行时,执行类中的方法

5.运行时,校验属性是否属于某个类

6.实现动态代理

3.3 反射怎么用

通过反射实现,类中的属性、方法的获取。还可以运行类中的方法。

创建Class对象的几种方式:

1.类名.class

2.Class.forName

3.对象名.getClass

代码演示:获取类中的属性

public static void main(String[] args) {
     
	//1.创建反射对象--Class
	Class<Student> clz=Student.class;
	//2.获取Student类中的属性
	//公共属性,包含继承属性
	Field[] arrF=clz.getFields();
	//所有属性,不包含继承的属性
	Field[] arrF2=clz.getDeclaredFields();
	//3.显示 获取到的属性
	System.err.println("公共属性,包含继承属性:"+Arrays.toString(arrF));
	System.err.println("所有属性,不包含继承的属性:"+Arrays.toString(arrF2));
}

代码演示:获取类中的方法

public static void main(String[] args) {
     
	//1.获取反射对象
	Class<Student> clz=Student.class;
	//2.获取对象中的方法
	//公共方法,包含继承方法
	Method[] arrM=clz.getMethods();
	//所有方法,不包含继承方法
	Method[] arrM2=clz.getDeclaredMethods();
	//3.显示对应的方法
	System.err.println("公共方法:"+Arrays.toString(arrM));
	System.err.println("所有方法:"+Arrays.toString(arrM2));
}

代码演示:通过反射执行类中的方法

public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
     
	//1.获取反射对象
	Class<Student> clz=Student.class;
	//执行公共方法
	//2.获取要运行的方法对象
	Method m=clz.getDeclaredMethod("eat");
	//3.创建对应的对象
	Student s=clz.newInstance();
	//4.执行方法
	/*
	 * invoke 参数说明:
	 * 1.方法对应的对象
	 * 2.方法需要的参数,可变参数*/
	m.invoke(s);
	
	//执行私有方法
	Method rm=clz.getDeclaredMethod("run");
	//设置 是否过滤访问校验  私有方法或属性,必须设置过滤访问校验
	rm.setAccessible(true);
	rm.invoke(s);
}

四、进程和线程

4.1 进程

反射和多线程基础_第1张图片

进程:软件在运行时一种状态。会占用CPU、内存等号资源

正在运行的程序

进程的特点:

1.独立性

2.动态性

3.并发性

4.2 线程

线程:代码的执行路径,是进程的组成部分,一个进程可以有多个线程。每个线程都可以执行自己的内容或者多个线程共同执行一个任务

有了多线程,就可以同时干多件事情

线程是CPU的最小调度单位,CPU可以很快的在多个线程间实现切换。

运行时的线程,随时都可以被CPU给挂起。

线程的抢占发生在任意时期。

4.3 进程和线程的区别

1、一个程序,可以有多个进程

2、一个进程可以有多个线程。但是必须要有一个主线程

3、进程间不能共享资源,但是线程间可以共享资源。

五、线程的体验和创建方式

敲黑板:java中的main方法其实就是主线程,main内部的代码执行都是主线程在执行。

我们自己手动创建线程,都叫子线程

5.1 线程初体验
	public static void main(String[] args) {
     
		//1.创建线程接口的对象  匿名内部类-实例化 接口、抽象类
		Runnable rb=new Runnable() {
     
			@Override
			public void run() {
     
				System.err.println("我是子线程-"+
			Thread.currentThread().getName());
			}
		};
		//2.创建线程对象,并定义线程要做的事情
		Thread td=new Thread(rb);
		//3.启动线程
		//td.start();//才是子线程在运行
		
		td.run();//这样的话,代码的运行就是主线程运行。
		System.err.println("主线程-"+Thread.currentThread().getName());
	}
5.2 线程的说明

1.Java中的线程类:Thread

2.Java中的线程都需要接口,线程接口:Runnable

​ 接口内部只有一个方法:run

​ public void run();

3.每次在写子线程的时候,都需要在run方法内部实现自己要干的事情

4.启动线程是用的start方法

5.3 线程的创建方式

日常使用线程,常用的三种创建方式。

1.实现Runnable接口

2.自定义类实现Thread类的子类,重写run方法

3.实现Callable接口

5.4 实现Runnable接口实现线程

1.采用匿名内部类 直接完成接口的实例化,并重写run方法

2.自定义类实现接口,重写run方法

代码演示:基于Runnable接口实现线程:

实现Runnable接口

public class MyRunnable implements Runnable{
     
	@Override
	public void run() {
     
		//子线程要做的事情
		//通过子线程 实现数羊
		for(int i=1;i<101;i++) {
     
			System.err.println("子线程-数羊:第"+i+"只羊");
		}
	}
}

main方法测试

	public static void main(String[] args) {
     
		//1.创建接口的实例对象
		MyRunnable mr=new MyRunnable();
		//2.创建线程对象
		Thread td=new Thread(mr);
		//3.启动线程
		td.start();
	}

敲黑板:实际上我们可以实现匿名内部类来实现Runnable的接口。

5.5 继承Thread类实现线程

创建类继承Thread,并重写run方法

public class HelloThread  extends Thread{
     
	@Override
	public void run() {
     
		System.err.println(" 继承线程类 实现子线程");
	}
}
public static void main(String[] args) {
     
		//1.实例化自定义线程类对象
		HelloThread ht=new HelloThread();
		//2.启动线程
		ht.start();
}
5.6 使用Callable实现线程

jdk新版本推出线程创建方式,线程可以带返回值。

1.实现Callable接口,并指定线程的返回值类型

2.创建FutureTask对象

3.创新线程对象,并传递任务对象

4.启动线程

5.获取线程的返回值

public class MyCallable implements Callable<Integer>{
     
	@Override
	public Integer call() throws Exception {
     
		System.err.println("子线程,带返回值的");
		return new Random().nextInt(10);
	}
}
	public static void main(String[] args) throws InterruptedException, ExecutionException {
     
		//1.创建 Callable接口的实现类对象
		MyCallable mc=new MyCallable();
		//2.创建任务对象
		FutureTask<Integer> ft=new FutureTask<Integer>(mc);
		//3.创新线程对象
		Thread td=new Thread(ft);
		//4.启动线程
		td.start();
		//5.获取线程的返回值 只有在线程执行结束之后才会返回
		System.err.println("返回值:"+ft.get());
	}
5.7 三种创建方式的区别

继承Thread类:

​ 编写简单、单继承,所以这种类无法再继承其他类、无法实现多个线程的资源共享、扩展性无

实现Runnable接口:

​ 编写复杂一点,接口可以多实现,可以实现多个线程的资源共享 推荐使用

实现Callable接口:

编码复杂,可以实现线程执行完之后进行值的返回

开发中,需要线程返回值,就使用Callable,不需要返回值的就可以Runnable5.8

六、线程状态

6.1 线程的状态(生命周期)

线程有五大状态,分别是新建、就绪、运行、阻塞、销毁

新建:

当我们实例化线程对象的时候,线程就是新建状态

就绪:

当我们调用线程的start方法之后,线程就会进入就绪状态

处于该状态的线程,随时都可以获取CPU调度

运行:

线程获取CPU的调度之后,线程抢到了时间片,可以用来运行自己任务

阻塞:

当线程因为资源竞争,或主动方法调用,让线程进入到阻塞。

常见:sleep、wait、join等等

销毁:

当线程的run方法执行结束之后,就会进入到销毁状态

敲黑板:程序的结束就是指的内部多的所有线程全部进入到了销毁状态

反射和多线程基础_第2张图片

七、线程的分类

7.1 线程的种类

线程分为:用户线程和守护线程

Java中默认创建的线程就是用户线程。

代码演示:用户线程和守护线程

	public static void main(String[] args) {
     
		// 代码演示线程的类型 用户线程和守护线程
		//默认的就是用户线程
		Thread th=new Thread(new Runnable() {
     
			
			@Override
			public void run() {
     
				// TODO Auto-generated method stub
				System.err.println("子线程");
			}
		});
		th.start();
		//创建守护线程
		Thread th2=new Thread(new Runnable() {
     
					@Override
					public void run() {
     
						// TODO Auto-generated method stub
						System.err.println("子线程--守护线程");
					}
				});
		//设置当前的线程对象是否为守护线程,默认为false
		th2.setDaemon(true);
		//启动线程
		th2.start();
	}
7.2 用户线程和守护线程的区别

主线程和GC线程就是经典-用户线程和守护线程。GC线程守护主线程

守护线程的特点:当守护的用户线程销毁的时候,守护线程也会跟着消亡。无论守护线程是否执行结束都会随着用户线程一起销毁。

皇帝和妃子的故事:

皇帝–>用户线程

妃子们–>守护线程

7.3 代码演示
public class LogRunable implements Runnable{
     

	@Override
	public void run() {
     
		//死循环
		while(true) {
     
			//间隔3秒 打印日志……
			try {
     
				Thread.sleep(3000);
			} catch (InterruptedException e) {
     
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("守护线程:记录日志中……");
		}
	}
}
	public static void main(String[] args) {
     
		//演示 用户线程和守护线程
		//创建用户线程
		Thread td=new Thread(new Runnable() {
     
			
			@Override
			public void run() {
     
				//拥有守护线程
				Thread t=new Thread(new LogRunable());
				//设置为守护线程 守护的是当前的用户线程
				t.setDaemon(true);
				t.start();
				for(int i=1;i<10001;i++) {
     
					if(i%33==0&& i%77==0) {
     
						try {
     
							Thread.sleep(500);
						} catch (InterruptedException e) {
     
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						System.err.println("用户线程--"+i);
					}
				}
			}
		});
		//启动用户线程
		td.start();
	}

当用户线程销毁的时候,会将自己的守护线程一起销毁!

八、线程的优先级

8.1 优先级

线程的优先级就是线程获得CPU的概率,优先级越高,获取CPU的概率越大

从小到大,1-10之间。10是优先级最高,默认的优先级是5.

8.2 设置优先级

通过线程的setPriority 设置线程的优先级

通过线程的getPriority获取线程的优先级

设置优先级需要在start之前设置。

九、线程练习

9.1 使用多线程模拟 骚磊的生活

小磊同学,看电视、还可以玩游戏、说话聊天。请用多线程的形式,展示小磊的生活

代码演示:

public static void main(String[] args) {
     
		//三个线程-分别做不同的事情
		//匿名内部类 实现
		Thread td1=new Thread(new Runnable() {
     	
			@Override
			public void run() {
     
				// TODO Auto-generated method stub
				System.err.println("小磊在看电视--->爱情电视剧 泡沫剧");
			}
		});
		td1.start();
		
		Thread td2=new Thread(new Runnable() {
     	
			@Override
			public void run() {
     
				// TODO Auto-generated method stub
				System.err.println("小磊在玩游戏--->斗地主、俄罗斯方块、扫雷");
			}
		});
		td2.start();
		
		Thread td3=new Thread(new Runnable() {
     	
			@Override
			public void run() {
     
				// TODO Auto-generated method stub
				System.err.println("小磊在聊天--->单身男士喜欢的内容");
			}
		});
		td3.start();
		
	}

扩展知识:

1.Lambda表达式

Lambda是JDK8之后支持的一种简写模式。可以快速的实现接口的实例化

语法格式:(参数)->{方法重写}

规则:

​ 1.接口

​ 2.接口中只能有一个抽象方法

​ 3.Lambda表达式的结果是一个对象

代码演示:

接口

public interface IEat {
     

	void eat();
}
	public static void main(String[] args) {
     
		//1.基于Lambda表达式完成接口的实例化  
		IEat ie=()->System.err.println("吃啥呢?");
		ie.eat();
	}

你可能感兴趣的:(反射和多线程基础)